SEARCH_ACTION = "search" GO_ACTION = "go" FOLLOW_ACTION = "follow" SEE_ACTION = "see" BEGIN_ACTION = "begin" AVOID_ACTION = "avoid" PATROL_ACTION = "patrol" CARRY_ACTION = "carry" STAY_ACTION = "stay" ACTIVATE_ACTION = "activate" DEACTIVATE_ACTION = "deactivate" UNDERSTOOD_SENSES = set(ACTION_ALIASES.keys()) class Event(object):
    """An event in the environment."""

    def __init__(self, theme, sensor):
        self.theme = theme
        self.sensor = sensor

    def __str__(self, lvl=0):
        indent = '\t'*(lvl)
        return 'Event:\n' + \
               indent + '\tSensor: ' + str(self.sensor) + '\n' + \
               (indent + '\tTheme: ' + self.theme.__str__(lvl + 1) if self.theme else '')

    def __repr__(self):
        return str(self)

    def readable(self):
        return 'I %s %s' % (self.sensor, self.theme.readable(case=False)) class Assertion(object):
    """Asserts the existence or property of an Entity in the world."""

    def __init__(self, theme, location, existential=False):
        self.theme = theme
        self.location = location
        self.existential = existential

    def readable(self):
        return '{!r} is/are in {!r}'.format(self.theme.readable(case=True), self.location.readable())

    def __str__(self, lvl=0):
        indent = '\t'*(lvl)
        return 'Assertion: \n' + \
            (indent + '\tTheme: %s\n' % self.theme.__str__(lvl + 1) if self.theme else '') + \
            (indent + '\tLocation: %s\n' % self.location.__str__(lvl + 1) if self.location else '')+ \
            indent + '\tExistential: %s' % str(self.existential)

    def __repr__(self):
        return str(self) def process_parse_tree(parse_tree_input, text_input, knowledge_base=None, quiet=False):
    """Produces semantic interpretations of parse trees."""
    if not quiet:
        print "Processing:", repr(text_input)

    # Perform tree operations
    frames = extract_frames_from_parse(parse_tree_input)
    if not quiet:
        print "Semantic frames:", frames

    # Extract meaning
    semantic_structures = create_semantic_structures(frames)

    # Update KB
    if knowledge_base:
        kb_response = knowledge_base.process_semantic_structures(semantic_structures, source='cmdr')
    else:
        kb_response = ''

    # Extract commands.
    new_commands = [item for item in semantic_structures if isinstance(item, Command)]
    if knowledge_base:
        knowledge_base.fill_commands(new_commands)
    if new_commands and not quiet:
        print "New commands:"
        for command in new_commands:
            print command

    if kb_response and not quiet:
        print "KB response:", kb_response

    return (frames, new_commands, kb_response) class PipelineClient(object):
    """Provides a client to the PipelineHost."""

    def __init__(self, port=DEFAULT_PORT, hostname='localhost', verbose=False):
        self.verbose = verbose
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.sock.connect((hostname, port))
        except socket.error:
            raise IOError("Could not connect to pipelinehost on %s:%d. "
                          "Make sure that pipelinehost is running." %
                          (hostname, port))

    def parse(self, text, force_nouns=None, force_verbs=None):
        """Parse text using a remote pipeline."""
        # Strip any trailing punctuation.
        text = text.strip()
        # Wrap in kwargs
        return _socket_parse(asocket=self.sock, text=text, force_nouns=force_nouns,
                             force_verbs=force_verbs, verbose=self.verbose)

    def close(self):
        """Close the connection to the pipeline host.

        If you need the connection closed promptly, it's wise to call
        this, but garbage collection will accomplish the same purpose.
        """
        try:
            self.sock.shutdown(socket.SHUT_RDWR)
        except socket.error:
            pass
        self.sock.close() class KnowledgeBase:
    """Stores knowledge about the world"""
    def __init__(self, other_agents=None):
        self.facts = [MapFact()]
        if other_agents:
            self.facts.extend(KnowledgeFact(agent) for agent in other_agents)
        self.last_object = None
        self.last_location = None
    def process_semantic_structures(self, semantic_structures, source=None):
        """Processes semantic structures and returns a response
        if given a query"""

        response = ''
        for structure in semantic_structures:
            if isinstance(structure, Assertion):
                self.assimilate(structure, source)
                response = 'Got it. %s' % structure.readable()
            elif isinstance(structure, Query):
                response = self.query(structure)
            # Assertions, Commands have themes and locations that 
            # may be referenced later
            if isinstance(structure, Command):
                # Only replace resolved object 
                # (theme has priority over condition)
                if structure.theme and not is_pronoun(structure.theme.name):
                    self.last_object = structure.theme
                elif structure.condition and structure.condition.theme \
                        and not is_pronoun(structure.condition.theme.name):
                    self.last_object = structure.condition.theme
                # Only replace resolved locations 
                # (theme has priority over condition)
                if structure.location and structure.location.name != 'there':
                    self.last_location = structure.location
                elif structure.condition and \
                        isinstance(structure.condition, Assertion) and \
                        structure.condition.location and \
                        structure.condition.location.name != 'there':
                    self.last_location = structure.condition.location
            elif isinstance(structure, Assertion):
                if structure.theme and not is_pronoun(structure.theme.name):
                    self.last_object = structure.theme
                if structure.location and structure.location.name != 'there':
                    self.last_location = structure.location
        return response

    def assimilate(self, assertion, source):
        """ Assimilates new piece of knowledge (Assertion) """
        for f in self.facts:
            f.assimilate(assertion, source)

    def query(self, query):
        """Reponds to a given query"""
        # Ignore queries like "Where are you?"
        if isinstance(query, LocationQuery) and query.theme.name == 'you':
            return None
        responses = [r for r in (
            fact.query(query) for fact in self.facts) if r is not None]
        if len(responses) > 0:
            return '\n'.join(responses)
        return None

    def fill_commands(self, commands):
        """Fills in underspecified fields
        based on current knowledge"""
        for c in commands:
            if isinstance(c, Command):
                if self.last_object:
                    if c.theme and is_pronoun(c.theme.name):
                        c.theme.name = self.last_object.name
                    if c.patient and is_pronoun(c.patient.name):
                        c.patient.name = self.last_object.name
                    if c.condition and c.condition.theme\
                            and is_pronoun(c.condition.theme.name):
                        c.condition.theme.name = self.last_object.name
                if self.last_location:
                    if c.location and c.location.name == 'there':
                        c.location.name = self.last_location.name
                for f in self.facts:
                    if isinstance(f, MapFact):
                        if c.destination and not c.source:
                            # Fill in source
                            if c.theme:
                                result = f.query_map(None, c.theme)
                                if len(result) > 0:
                                    c.source = result[0]
                        if not c.location and not c.destination \
                                and not c.source:
                            # Fill in location
                            if c.theme:
                                result = f.query_map(None, c.theme)
                                if len(result) > 0:
                                    c.location = result[0]
    def __str__(self):
        return '\n'.join(str(f) for f in self.facts) def env(text):
    """Add an environment state marker in front of a string."""
    return ENV_STATE + text def and_(propostions, delim=''):
    """Add logical and to the arguments"""
    return parens((space(AND) + delim).join(propostions)) def or_(propostions, delim=''):
    """Add logical or to the arguments"""
    return parens((space(OR) + delim).join(propostions)) def sys_(text):
    """Add a robot state marker in front of a string."""
    return ROBOT_STATE + text def not_(text):
    """Add a not operator in front of a string."""
    return NOT + text def iff(prop1, prop2):
    """Connect two propositions with if and only if."""
    return parens(prop1 + space(IFF) + prop2) def next_(text):
    """Wrap text in next()."""
    return "next" + parens(text) def always(text):
    """Wrap text in always."""
    return parens(ALWAYS + parens(text)) def always_eventually(text):
    """Wrap text in always."""
    return parens(ALWAYS + EVENTUALLY + parens(text)) def implies(prop1, prop2):
    """Connect two propositions with implies."""
    return parens(prop1 + space(TO) + prop2) def space(text):
    """Wrap text in spaces."""
    return " " + text + " " def mutex_(items, include_all_off=False):
    """Create a system proposition mutex over the given items."""
    return or_([and_([item1] +
                     [not_(item2) for item2 in items if item2 != item1])
                for item1 in items] +
               ([and_([not_(item) for item in items])] if include_all_off else [])) ALWAYS = "[]" EVENTUALLY = "<>" OR = "|"
import sys
import re
from collections import OrderedDict, defaultdict
from copy import deepcopy
from semantics.lexical_constants import (
    SEARCH_ACTION, GO_ACTION, FOLLOW_ACTION, SEE_ACTION, BEGIN_ACTION,
    AVOID_ACTION, PATROL_ACTION, CARRY_ACTION, STAY_ACTION, ACTIVATE_ACTION,
    DEACTIVATE_ACTION, UNDERSTOOD_SENSES)
from semantics.new_structures import Event, Assertion
from semantics.parsing import process_parse_tree
from pipelinehost import PipelineClient
from semantics.new_knowledge import KnowledgeBase
from ltlbroom.ltl import (
    env, and_, or_, sys_, not_, iff, next_, always, always_eventually, implies,
    space, mutex_, ALWAYS, EVENTUALLY, OR)
            return self._gen_avoid(command)

        try:
            regions = [location.name for location in self._expand_argument(command.location, command)]
        except AttributeError:
            raise KeyError("Could not understand location for 'go' command.")
        # Raise an error if any of the regions are bad.
        for region in regions:
            if region not in self.regions:
                raise KeyError("Cannot go to location {!r} "
                               "because it is not on the map.".format(region))

        sys_chunks = []
        mem_props = []
        for region in regions:
            # Set memory false initially
            mem_prop = _prop_mem(region, VISIT)
            explanation1 = "Initially, {!r} has not been visited.".format(region)
            init_off = not_(sys_(mem_prop))
            init_chunk = SpecChunk(explanation1, [init_off], SpecChunk.SYS, command)
            sys_chunks.append(init_chunk)

            sys_lines = _frag_atleastonce(mem_prop, next_(sys_(region)))
            explanation2 = "Visit {!r}.".format(region)
            sys_chunk = SpecChunk(explanation2, sys_lines, SpecChunk.SYS, command)
            mem_props.append(mem_prop)
            sys_chunks.append(sys_chunk)

        return (sys_chunks, [], mem_props, [])

    def _gen_avoid(self, command):
        """Generate statements for never going to a location."""
        regions = [location.name for location in self._expand_argument(command.location, command)]
        spec_chunks = []
        for region in regions:
            explanation1 = "Do not go to {!r}.".format(region)
            sys_lines1 = SpecChunk(explanation1, [always(not_(sys_(region)))],
                                   SpecChunk.SYS, command)
            explanation2 = "The robot does not begin in {!r}.".format(region)
            sys_lines2 = SpecChunk(explanation2, [not_(sys_(region))], SpecChunk.SYS, command)
            spec_chunks.extend([sys_lines1, sys_lines2])

        return (spec_chunks, [], [], [])

    def _gen_search(self, command):
        """Generate statements for searching a region."""
        regions = [location.name for location in self._expand_argument(command.location, command)]
        spec_chunks = []
        mem_props = []
        for region in regions:
            # Set memory false initially
            mem_prop = _prop_mem(region, SWEEP)
            init_off = [not_(sys_(mem_prop))]
            explanation0 = "Initially, {!r} has not been searched.".format(region)
            spec_chunks.append(SpecChunk(explanation0, init_off, SpecChunk.SYS, command))

            explanation1 = "Complete a search in {!r}.".format(region)
            cic_frag, cic_env = _frag_complete_context(SWEEP, sys_(region))
            alo_sys = _frag_atleastonce(mem_prop, cic_frag)
            mem_props.append(mem_prop)
            spec_chunks.append(SpecChunk(explanation1, alo_sys, SpecChunk.SYS, command))

        explanation2 = "Assume that searches eventually complete."
        env_chunk = SpecChunk(explanation2, cic_env, SpecChunk.ENV, command)

        return (spec_chunks, [env_chunk], mem_props, [_prop_actuator_done(SWEEP)])

    def _gen_activate(self, command, negated=False):
        """Generate statements for activating an actuator."""
        try:
            actuator = command.theme.name
        except AttributeError:
            raise KeyError("Missing actuator for activate/deactivate.")

        # If negation isn't set, allow the command to set it
        negated = negated or command.negation
        actuator_frag = sys_(actuator) if not negated else not_(sys_(actuator))
        when = "Always" if not negated else "Never"

        chunks = []
        if command.location:
            regions = [location.name for location in
                       self._expand_argument(command.location, command)]
            for region in regions:
                # Generate a location-restricted action
                explanation = "{} activate {!r} in {!r}.".format(when, actuator, region)
                formula = always(implies(sys_(region), actuator_frag))
                chunks.append(SpecChunk(explanation, [formula], SpecChunk.SYS, command))
        else:
            # Always activate
            explanation = "{} activate {!r}.".format(when, actuator)
            formula = always(actuator_frag)
            chunks.append(SpecChunk(explanation, [formula], SpecChunk.SYS, command))

        return (chunks, [], [], [])

    def _gen_deactivate(self, command):
        """Generate statements for deactivating an actuator."""
        return self._gen_activate(command, True)


def _chunk_deliver(command, item, dest, mem_dest):
    """Return a chunk representing delivering an item to its destination."""
    delivery_explanation = "Deliver {!r} to {!r}.".format(item, dest)
    delivery_frag = and_([next_(sys_(dest)), next_(sys_(DROP))])
    delivery_chunk = SpecChunk(delivery_explanation, _frag_atleastonce(mem_dest, delivery_frag),
                               SpecChunk.SYS, command)
    return delivery_chunk


def _frag_atleastonce(mem_prop, fragment):
    """Generate fragments for performing an action at least once by using a memory proposition."""
    return [always(iff(next_(sys_(mem_prop)), or_((sys_(mem_prop), fragment)))),
            always_eventually(sys_(mem_prop))]


def _frag_complete_context(actuator, context_prop):
    """Generate fragments for completing an action in context."""
    actuator_done = _prop_actuator_done(actuator)
    eventually_actuator = always_eventually(env(actuator_done))

    return [and_((sys_(actuator), next_(env(actuator_done)), context_prop)), [eventually_actuator]]