Example #1
0
    def loadProjectAndRegions(self, proj):
        """
        This function is used to (re)initialize region objects and proj object.
        """
        self.proj = proj
        self.regions = self.proj.rfi.regions  # contains decomposed names
        if self.fastslow:
            self.regionCompleted_domain = strategy.Domain(
                "regionCompleted", proj.rfi.regions, strategy.Domain.B0_IS_MSB)
        self.region_domain = strategy.Domain("region", proj.rfi.regions,
                                             strategy.Domain.B0_IS_MSB)

        #find out mapping from new_names to old ones
        self.newRegionNameToOld = {}
        for rname, subregs in proj.regionMapping.iteritems():
            for newReg in subregs:
                self.newRegionNameToOld[newReg] = rname

        # form regionList with original names
        self.regionList = []
        for region in self.regions:
            self.regionList.append(self.newRegionNameToOld[region.name])

        # for mapping original region name to bit encoding
        self.bitEncode = parseEnglishToLTL.bitEncoding(
            len(self.regionList),
            int(numpy.ceil(numpy.log2(len(self.regionList)))))
Example #2
0
    def postprocessLTL(self, text, sensorList, robotPropList):
        # TODO: make everything use this
        if self.proj.compile_options["decompose"]:
            # substitute decomposed region names
            for r in self.proj.rfi.regions:
                if not (r.isObstacle or r.name.lower() == "boundary"):
                    text = re.sub('\\bs\.' + r.name + '\\b', "("+' | '.join(["s."+x for x in self.parser.proj.regionMapping[r.name]])+")", text)
                    text = re.sub('\\be\.' + r.name + '\\b', "("+' | '.join(["e."+x for x in self.parser.proj.regionMapping[r.name]])+")", text)

        if self.proj.compile_options["decompose"]:
            regionList = [x.name for x in self.parser.proj.rfi.regions]
        else:
            regionList = [x.name for x in self.proj.rfi.regions]

        # Define the number of bits needed to encode the regions
        numBits = int(math.ceil(math.log(len(regionList),2)))

        # creating the region bit encoding
        bitEncode = bitEncoding(len(regionList),numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']

        # switch to bit encodings for regions
        if self.proj.compile_options["use_region_bit_encoding"]:
            text = replaceRegionName(text, bitEncode, regionList)

        text = self.substituteMacros(text)

        return text
Example #3
0
    def replaceIndividualSbitsToGroupSbits(self, LTLList):
        """
        This function takes in an LTL list, extract sbits and put in the right bits afterwards
        """
        numBits = int(math.ceil(math.log(len(self.proj.rfi.regions),2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(self.proj.rfi.regions), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']
        envBitEnc = bitEncode['env']
        envNextBitEnc = bitEncode['envNext']

        newLTLList = sets.Set([])
        #newLTLList = []

        for LTLStr in LTLList: # LTLStr are of the form  a | b | c
            propList = sets.Set(LTLStr.split(' | '))
            # run four times
            propList = self.replaceIndividualSbitsToGroupSbitsForTypeOfBits(numBits, '!?next\(s.bit(?P<bitNo>\d+)\)', nextBitEnc, propList)
            propList = self.replaceIndividualSbitsToGroupSbitsForTypeOfBits(numBits, '!?s.bit(?P<bitNo>\d+)', currBitEnc, propList)
            propList = self.replaceIndividualSbitsToGroupSbitsForTypeOfBits(numBits, '!?next\(e.sbit(?P<bitNo>\d+)\)', envNextBitEnc, propList)
            propList = self.replaceIndividualSbitsToGroupSbitsForTypeOfBits(numBits, '!?e.sbit(?P<bitNo>\d+)', envBitEnc, propList)

            #newLTLList.append(' | '.join(propList))
            newLTLList.add(propList)

        #return '&\n'.join(['('+x+')' for x in newLTLList])
        return '&\n'.join(['('+' | '.join(x)+')' for x in newLTLList])
Example #4
0
    def write_cost_file(self, compiler):
        """ Generates *.cost file from the cost text supplied by the specification
        :param compiler: A parser
        :type compiler: SpecCompiler
        :return: None
        """

        costFile = open(self._cost_filename(), 'w')

        # Must use bit encoding with slugs
        assert self.proj.compile_options["use_region_bit_encoding"]

        # Regular Expressions used for parsing cost spec
        RE_FACTOR = re.compile('\d \d (<|>)', re.IGNORECASE)
        RE_ENTRY = re.compile('(\\d+\\.\\d+)\\s(.*)', re.IGNORECASE)

        # Step through Cost Specification
        costText = []
        for line in self.cost_text.split('\n'):
            # Check if First Line defines the Cost Factors for waiting and
            # delay costs
            if len(costText) == 0:
                if RE_FACTOR.search(line) is not None:
                    costText.append(line)
                    continue
                else:
                    RuntimeError('The first line of the cost spec must ' +
                                 'always represent the cost factors for' +
                                 'waiting and delay cost.')

            # Split each line into the value and formula portions
            entryRE = RE_ENTRY.search(line)
            value = entryRE.group(1)
            formula = entryRE.group(2)

            # Replace region names in cost with decomposed region names
            formula = compiler._subDecompedRegion(formula)

            # Replace Formula with bit encoding
            regionList = compiler.getRegionList()
            numBits = int(math.ceil(math.log(len(regionList), 2)))
            bitEncode = bitEncoding(len(regionList), numBits)
            formula = replaceRegionName(formula, bitEncode, regionList)

            # Replace Input (Sensor) names
            formula = self._replace_input_names(formula)

            # Replace Output (Actuator) names
            formula = self._replace_output_names(formula)

            # Parse into SLUGS format (Postfix notation)
            formulaTree = parseLTL(formula + ';')
            formula = parseSimpleFormula(formulaTree[1], False)
            formula = ' '.join(formula)

            # Append to cost text
            costText.append(value + ' ' + str(formula))

        # Write costText to file
        costFile.write("\n".join(costText))
Example #5
0
def createTopologyFragment(adjData, regions, use_bits=True):
    if use_bits:
        numBits = int(math.ceil(math.log(len(adjData),2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']

    # The topological relation (adjacency)
    adjFormulas = []

    for Origin in range(len(adjData)):
        # from region i we can stay in region i
        adjFormula = '\t\t\t []( ('
        adjFormula = adjFormula + (currBitEnc[Origin] if use_bits else "s."+regions[Origin].name)
        adjFormula = adjFormula + ') -> ( ('
        adjFormula = adjFormula + (nextBitEnc[Origin] if use_bits else "next(s."+regions[Origin].name+")")
        adjFormula = adjFormula + ')'
        
        for dest in range(len(adjData)):
            if adjData[Origin][dest]:
                # not empty, hence there is a transition
                adjFormula = adjFormula + '\n\t\t\t\t\t\t\t\t\t| ('
                adjFormula = adjFormula + (nextBitEnc[dest] if use_bits else "next(s."+regions[dest].name+")")
                adjFormula = adjFormula + ') '

        # closing this region
        adjFormula = adjFormula + ' ) ) '

        adjFormulas.append(adjFormula)

    # In a BDD strategy, it's best to explicitly exclude these
    adjFormulas.append("[]"+createInitialRegionFragment(regions, use_bits))

    return " & \n".join(adjFormulas)
Example #6
0
def createInitialRegionFragment(regions, use_bits=True):
    # Setting the system initial formula to allow only valid
    #  region (encoding). This may be redundant if an initial region is
    #  specified, but it is here to ensure the system cannot start from
    #  an invalid, or empty region (encoding).
    if use_bits:
        numBits = int(math.ceil(math.log(len(regions), 2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(regions), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']

        initreg_formula = '\t\t\t( ' + currBitEnc[0] + ' \n'
        for regionInd in range(1, len(currBitEnc)):
            initreg_formula = initreg_formula + '\t\t\t\t | ' + currBitEnc[
                regionInd] + '\n'
        initreg_formula = initreg_formula + '\t\t\t) \n'
    else:
        initreg_formula = "\n\t({})".format(" | ".join([
            "({})".format(" & ".join([
                "s." + r2.name if r is r2 else "!s." + r2.name
                for r2 in regions
            ])) for r in regions
        ]))

    return initreg_formula
Example #7
0
def createIAInitialEnvRegionFragment(regions, use_bits=True, nextProp=False):
    # Setting the system initial formula to allow only valid
    #  region (encoding). This may be redundant if an initial region is
    #  specified, but it is here to ensure the system cannot start from
    #  an invalid, or empty region (encoding).
    if use_bits:
        numBits = int(math.ceil(math.log(len(regions), 2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(regions), numBits)
        envBitEnc = bitEncode['env']
        envNextBitEnc = bitEncode['envNext']

        if nextProp:
            initreg_formula_list = []
            for regionInd in range(0, len(envNextBitEnc)):
                initreg_formula = '( ' + envNextBitEnc[regionInd]  #+ ' \n'
                for notRegionInd in range(0, len(envNextBitEnc)):
                    if notRegionInd != regionInd:
                        initreg_formula = initreg_formula + '& !' + envNextBitEnc[
                            notRegionInd]  #+ '\n'
                initreg_formula = initreg_formula + ')'
                initreg_formula_list.append(initreg_formula)

            initreg_formula = '(' + '|\n'.join(initreg_formula_list) + ')'
        else:
            initreg_formula_list = []
            for regionInd in range(0, len(envBitEnc)):
                initreg_formula = '( ' + envBitEnc[regionInd]  #+ ' \n'
                for notRegionInd in range(0, len(envBitEnc)):
                    if notRegionInd != regionInd:
                        initreg_formula = initreg_formula + '& !' + envBitEnc[
                            notRegionInd]  #+ '\n'
                initreg_formula = initreg_formula + ')'
                initreg_formula_list.append(initreg_formula)

            initreg_formula = '(' + '|\n'.join(initreg_formula_list) + ')'
    else:
        region_filtered = []
        for r in regions:
            if r.name != "boundary" and not r.isObstacle:
                region_filtered.append(r)
        if nextProp:
            initreg_formula = "\n\t({})".format(" | ".join([
                "({})".format(" & ".join([
                    "next(e." + r2.name + "_rc)" if r is r2 else "!next(e." +
                    r2.name + "_rc)" for r2 in region_filtered
                ])) for r in region_filtered
            ]))
        else:
            initreg_formula = "\n\t({})".format(" | ".join([
                "({})".format(" & ".join([
                    "e." + r2.name + "_rc" if r is r2 else "!e." + r2.name +
                    "_rc" for r2 in region_filtered
                ])) for r in region_filtered
            ]))

    return initreg_formula
Example #8
0
def createInitialEnvRegionFragment(regions,
                                   use_bits=True,
                                   nextProp=True,
                                   other_robot_name='',
                                   suffix=''):
    # Setting the system initial formula to allow only valid
    #  region (encoding). This may be redundant if an initial region is
    #  specified, but it is here to ensure the system cannot start from
    #  an invalid, or empty region (encoding).

    # skip boundary and obstacles
    regions_old = regions
    regions = []
    for reg in regions_old:
        if reg.name == 'boundary' or reg.isObstacle:
            continue
        else:
            regions.append(reg)

    if use_bits:
        numBits = int(math.ceil(math.log(len(regions), 2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(regions), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']

        initreg_formula_list = []
        for regionInd in range(0, len(currBitEnc)):
            initreg_formula = '( ' + currBitEnc[regionInd]  #+ ' \n'
            for notRegionInd in range(0, len(currBitEnc)):
                if notRegionInd != regionInd:
                    initreg_formula = initreg_formula + ' & !' + currBitEnc[
                        notRegionInd]  #+ '\n'
            initreg_formula = initreg_formula + ')'
            initreg_formula_list.append(initreg_formula)

        initreg_formula = '(' + '|\n'.join(initreg_formula_list) + ')'
    else:
        if nextProp:
            initreg_formula = "\n\t({})".format(" |\n ".join([
                "({})".format(" & ".join([
                    "next(e." + other_robot_name + '_' + r2.name + suffix +
                    ')' if r is r2 else "!next(e." + other_robot_name + '_' +
                    r2.name + suffix + ")" for r2 in regions
                ])) for r in regions
            ]))
        else:
            initreg_formula = "\n\t({})".format(" |\n ".join([
                "({})".format(" & ".join([
                    "e." + other_robot_name + '_' + r2.name +
                    suffix if r is r2 else "!e." + other_robot_name + '_' +
                    r2.name + suffix for r2 in regions
                ])) for r in regions
            ]))

    return initreg_formula
Example #9
0
def createTopologyFragment(adjData, regions, use_bits=True):
    if use_bits:
        numBits = int(math.ceil(math.log(len(adjData), 2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']

    # The topological relation (adjacency)
    adjFormulas = []

    for Origin in range(len(adjData)):
        if (regions[Origin].name == 'boundary' or regions[Origin].isObstacle):
            continue
        # from region i we can stay in region i
        adjFormula = '\t\t\t []( ('
        adjFormula = adjFormula + (currBitEnc[Origin] if use_bits else "s." +
                                   regions[Origin].name)
        adjFormula = adjFormula + ') -> ( ('
        adjFormula = adjFormula + (nextBitEnc[Origin] if use_bits else
                                   "next(s." + regions[Origin].name + ")")
        adjFormula = adjFormula + ')'

        for dest in range(len(adjData)):
            if (regions[dest].name == 'boundary' or regions[dest].isObstacle):
                continue

            if adjData[Origin][dest]:
                # not empty, hence there is a transition
                adjFormula = adjFormula + '\n\t\t\t\t\t\t\t\t\t| ('
                adjFormula = adjFormula + (nextBitEnc[dest]
                                           if use_bits else "next(s." +
                                           regions[dest].name + ")")
                adjFormula = adjFormula + ') '

        # closing this region
        adjFormula = adjFormula + ' ) ) '

        adjFormulas.append(adjFormula)

    # In a BDD strategy, it's best to explicitly exclude these
    adjFormulas.append("[]" + createInitialRegionFragment(regions, use_bits))

    return " & \n".join(adjFormulas)
Example #10
0
def createInitialRegionFragment(regions, use_bits=True):
    # Setting the system initial formula to allow only valid
    #  region (encoding). This may be redundant if an initial region is
    #  specified, but it is here to ensure the system cannot start from
    #  an invalid, or empty region (encoding).
    if use_bits:
        numBits = int(math.ceil(math.log(len(regions),2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(regions), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']

        initreg_formula = '\t\t\t( ' + currBitEnc[0] + ' \n'
        for regionInd in range(1,len(currBitEnc)):
            initreg_formula = initreg_formula + '\t\t\t\t | ' + currBitEnc[regionInd] + '\n'
        initreg_formula = initreg_formula + '\t\t\t) \n'
    else:
        initreg_formula = "\n\t({})".format(" | ".join(["({})".format(" & ".join(["s."+r2.name if r is r2 else "!s."+r2.name for r2 in regions])) for r in regions]))
        
    return initreg_formula
    def getCurrentStateAsLTL(self, include_env=False):
        """ Return a boolean formula (as a string) capturing the current discrete state of the system (and, optionally, the environment as well) """

        # For now, only constrain pose (based on PoseHandler)
        current_region_idx = self._getCurrentRegionFromPose()
        # TODO: support non-bitvec
        numBits = int(math.ceil(math.log(len(self.proj.rfi.regions), 2)))
        current_region_LTL = bitEncoding(len(
            self.proj.rfi.regions), numBits)['current'][current_region_idx]

        return current_region_LTL

        if self.aut:
            # If we have current state in the automaton, use it (since it can capture
            # state of internal propositions).
            return ""
            #return fsa.stateToLTL(self.aut.current_state, include_env=include_env)
        else:
            # If we have no automaton yet, determine our state manually
            # TODO: support env
            # TODO: look at self.proj.currentConfig.initial_truths and pose
            return ""
Example #12
0
def createTopologyFragment(adjData, regions, use_bits=True):
    if use_bits:
        numBits = int(math.ceil(math.log(len(adjData), 2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']

    # The topological relation (adjacency)
    adjFormulas = []

    for Origin in range(len(adjData)):
        # from region i we can stay in region i
        adjFormula = '\t\t\t []( ('
        adjFormula = adjFormula + (currBitEnc[Origin] if use_bits else "s." +
                                   regions[Origin].name)
        adjFormula = adjFormula + ') -> ( ('
        adjFormula = adjFormula + (nextBitEnc[Origin] if use_bits else
                                   "next(s." + regions[Origin].name + ")")
        adjFormula = adjFormula + ')'

        for dest in range(len(adjData)):
            if adjData[Origin][dest]:
                # not empty, hence there is a transition
                adjFormula = adjFormula + '\n\t\t\t\t\t\t\t\t\t| ('
                adjFormula = adjFormula + (nextBitEnc[dest]
                                           if use_bits else "next(s." +
                                           regions[dest].name + ")")
                adjFormula = adjFormula + ') '

        # closing this region
        adjFormula = adjFormula + ' ) ) '

        adjFormulas.append(adjFormula)

    return " & \n".join(adjFormulas)
Example #13
0
def createIAMaintainDistanceSysTopologyFragment(regionMapping,
                                                regions,
                                                adjData,
                                                use_bits=True,
                                                other_robot_names_list=[]):
    """
    []( (next(e.other_robot_name_reg)) -> ( !(next(e.reg_rc)|()   & next(s.reg)|()  )))
    """
    # skip any boundary or obstacles
    regions_old = regions
    regions = []
    for reg in regions_old:
        if reg.name == 'boundary' or reg.isObstacle:
            continue
        else:
            regions.append(reg)

    if use_bits:
        numBits = int(math.ceil(math.log(len(regions), 2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(regions), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']
        envBitEnc = bitEncode['env']
        envNextBitEnc = bitEncode['envNext']

    # The topological relation (adjacency)
    adjFormulas = []

    if not other_robot_names_list:
        ltlmop_logger.info('robot_name not provided!')
        return

    # retrieve only the region names
    regionNames = [x.name for x in regions]
    for robot in other_robot_names_list:
        for reg, subregList in regionMapping.iteritems():
            reg = reg.encode('ascii', 'ignore')

            # skip boundary and obstacles
            skipRegion = False
            for subReg in subregList:
                if regions[regionNames.index(subReg)].isObstacle:
                    skipRegion = True
                    continue

            if reg == 'boundary' or reg == 'others' or skipRegion:
                continue

            toExcludeList = []
            toIncludeList = []
            for subReg in subregList:
                subRegIdx = regionNames.index(subReg)
                toExcludeList.append(subReg)

                # first find neighbour regions to exclude
                for destIdx in range(len(adjData)):
                    if adjData[regionNames.index(subReg)][destIdx]:
                        toExcludeList.append(regionNames[destIdx])

            #ltlmop_logger.debug("toExcludeList:" + str(toExcludeList))
            # 1st time
            for excludedSubReg in toExcludeList:
                for destIdx in range(len(adjData)):
                    if adjData[regionNames.index(
                            excludedSubReg
                    )][destIdx] and regionNames[destIdx] not in toExcludeList:
                        toIncludeList.append(regionNames[destIdx])

            # 2nd time
            toIncludeListNew = []
            for includedSubReg in toIncludeList:
                for destIdx in range(len(adjData)):
                    if adjData[regionNames.index(
                            includedSubReg)][destIdx] and regionNames[
                                destIdx] not in toExcludeList and regionNames[
                                    destIdx] not in toIncludeList:
                        toIncludeListNew.append(regionNames[destIdx])

            toIncludeList = list(set(toIncludeList + toIncludeListNew))

            # 3rd time
            toIncludeListNew = []
            for includedSubReg in toIncludeList:
                for destIdx in range(len(adjData)):
                    if adjData[regionNames.index(
                            includedSubReg)][destIdx] and regionNames[
                                destIdx] not in toExcludeList and regionNames[
                                    destIdx] not in toIncludeList:
                        toIncludeListNew.append(regionNames[destIdx])

            toIncludeList = list(set(toIncludeList + toIncludeListNew))
            #ltlmop_logger.debug("toIncludeList:" + str(toIncludeList))

            adjFormula = '\t\t\t []( next(e.'+ robot + '_' + reg + ') -> (' +\
                                    ' ! (' + '|'.join(filter(None, list(set([envNextBitEnc[regionNames.index(x)] if use_bits else "next(s."+ x + ")" for x in toExcludeList])))) + ') & ' +\
                                       '(' + '|'.join(filter(None, list(set([envNextBitEnc[regionNames.index(x)] if use_bits else "next(s."+ x + ")" for x in toIncludeList])))) + ') ) )'

            adjFormulas.append(adjFormula)

    return " & \n".join(adjFormulas)
Example #14
0
def createLTLfile(fileName, sensorList, robotPropList, adjData, spec):
    ''' This function writes the LTL file. It encodes the specification and 
    topological relation. 
    It takes as input a filename, the list of the
    sensor propositions, the list of robot propositions (without the regions),
    the adjacency data (transition data structure) and
    a dictionary containing the specification strings.
    '''

    fileName = fileName + '.ltl'
    ltlFile = open(fileName, 'w')

    numBits = int(numpy.ceil(numpy.log2(len(adjData))))
    bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
    currBitEnc = bitEncode['current']
    nextBitEnc = bitEncode['next']
    
    # Write the header and begining of the formula
    ltlFile.write(textwrap.dedent("""
    -- LTL specification file
    -- (Generated by the LTLMoP toolkit)

    """))
    ltlFile.write('LTLSPEC -- Assumptions\n')
    ltlFile.write('\t(\n')

    # Write the environment assumptions
    # from the 'spec' input 
    ltlFile.write(spec['EnvInit'])
    ltlFile.write(spec['EnvTrans'])
    ltlFile.write(spec['EnvGoals'])
    ltlFile.write('\n\t);\n\n')

    ltlFile.write('LTLSPEC -- Guarantees\n')
    ltlFile.write('\t(\n')

    # Write the desired robot behavior
    ltlFile.write(spec['SysInit'])

    # The topological relation (adjacency)
    for Origin in range(len(adjData)):
        # from region i we can stay in region i
        ltlFile.write('\t\t\t []( (')
        ltlFile.write(currBitEnc[Origin])
        ltlFile.write(') -> ( (')
        ltlFile.write(nextBitEnc[Origin])
        ltlFile.write(')')
        
        for dest in range(len(adjData)):
            if adjData[Origin][dest]:
                # not empty, hence there is a transition
                ltlFile.write('\n\t\t\t\t\t\t\t\t\t| (')
                ltlFile.write(nextBitEnc[dest])
                ltlFile.write(') ')

        # closing this region
        ltlFile.write(' ) ) & \n ')
    

    # The rest of the spec
    ltlFile.write(spec['SysTrans'])
    ltlFile.write(spec['SysGoals'])
    # Close the LTL formula
    ltlFile.write('\n\t);\n')

    # close the file
    ltlFile.close()
Example #15
0
def createSysMutualExclusion(regionMapping,
                             regions,
                             use_bits=True,
                             other_robot_name='',
                             use_robot_heading=False,
                             fastslow=False):
    """
    []( (next(e.other_robot_name_reg)) -> ( !(next(e.reg_rc))))
    """
    # skip any boundary or obstacles
    regions_old = regions
    regions = []
    for reg in regions_old:
        if reg.name == 'boundary' or reg.isObstacle:
            continue
        else:
            regions.append(reg)

    if use_bits:
        numBits = int(math.ceil(math.log(len(regions), 2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(regions), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']
        envBitEnc = bitEncode['env']
        envNextBitEnc = bitEncode['envNext']

    # The topological relation (adjacency)
    adjFormulas = []

    if not other_robot_name:
        ltlmop_logger.info('robot_name not provided!')
        return

    # retrieve only the region names
    regionNames = [x.name for x in regions]

    for reg, subregList in regionMapping.iteritems():
        reg = reg.encode('ascii', 'ignore')

        # skip boundary and obstacles
        skipRegion = False
        for subReg in subregList:
            if regions[regionNames.index(subReg)].isObstacle:
                skipRegion = True
                continue

        if reg == 'boundary' or reg == 'others' or skipRegion:
            continue

        # from region i we can stay in region i
        adjFormula = '\t\t\t []( ('
        adjFormula = adjFormula + ("next(e." + other_robot_name + '_' + reg +
                                   "_rc)" if use_robot_heading else "next(e." +
                                   other_robot_name + '_' + reg + ")")
        adjFormula = adjFormula + ') -> ( !('
        first = True
        for subReg in subregList:
            subRegIdx = regionNames.index(subReg)
            if first:
                first = False
            else:
                adjFormula = adjFormula + '\n\t\t\t\t\t\t\t\t\t| ('

            if fastslow:
                adjFormula = adjFormula + (envNextBitEnc[subRegIdx] if use_bits
                                           else "next(e." + subReg + "_rc)")
            else:
                adjFormula = adjFormula + (nextBitEnc[subRegIdx]
                                           if use_bits else "next(s." + subReg)
            adjFormula = adjFormula + ')'

        # closing this region
        adjFormula = adjFormula + ' ) )'
        adjFormulas.append(adjFormula)

    return " & \n".join(adjFormulas)
Example #16
0
def createIASysPropImpliesEnvPropLivenessFragment(sysProp,
                                                  regions,
                                                  envProp,
                                                  adjData,
                                                  use_bits=True,
                                                  other_robot_name=''):
    """
    Obtain for region: "[]<>((regionProp & regionProp_rc(envProp)) | (regionProp & !next(regionProp)))"
    Obtain for actions:"[]<>((actionProp & next(actionProp_ac(envProp))) |
                            (!actionProp & !next(actionProp_ac(envProp))) |
                            (actionProp & !next(actionProp)) |
                            (!actionProp & next(actionProp)) )"
    """
    # The topological relation (adjacency)
    adjFormulas = []

    if regions:
        if use_bits:
            numBits = int(math.ceil(math.log(len(adjData), 2)))
            # TODO: only calc bitencoding once
            bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
            currBitEnc = bitEncode['current']
            nextBitEnc = bitEncode['next']
            envBitEnc = bitEncode['env']
            envNextBitEnc = bitEncode['envNext']

        adjFormula = '\t\t\t []<>( '
        adjSubFormulaArray = []
        for Origin in range(len(regions)):
            # skip boundary and obstacles
            if (regions[Origin].name == 'boundary'
                    or regions[Origin].isObstacle):
                continue

            curProp = (currBitEnc[Origin] if use_bits else "s." +
                       regions[Origin].name)
            nextProp = (nextBitEnc[Origin] if use_bits else "next(s." +
                        regions[Origin].name + ")")
            # TODO: maybe pass in env region list and use it here instead
            nextEnvProp = (envNextBitEnc[Origin] if use_bits else "next(e." +
                           regions[Origin].name + "_rc)")
            adjSubFormulaArray.append('(' + curProp + ' & ' + nextEnvProp +
                                      ') | (' + curProp + ' & !' + nextProp +
                                      ')\n')

        # closing the formula
        adjFormula = adjFormula + "\t\t\t\t| ".join(adjSubFormulaArray)
        adjFormula = adjFormula + ' ) '

        adjFormulas.append(adjFormula)

    if len(sysProp):
        adjFormula = '\t\t\t []<>( '
        adjSubFormulaArray = []
        for idx in range(len(sysProp)):
            # from action to action completion
            if sysProp[idx] + "_ac" in envProp:

                curActProp = 's.' + sysProp[idx]
                nextActProp = 'next(s.' + sysProp[idx] + ')'
                nextEnvActProp = 'next(e.' + sysProp[idx] + '_ac)'
                # from region i we can stay in region i
                adjSubFormulaArray.append('(' + curActProp + ' & ' +
                                          nextEnvActProp + ') | (!' +
                                          curActProp + ' & !' +
                                          nextEnvActProp + ') | (' +
                                          curActProp + ' & !' + nextActProp +
                                          ') | (!' + curActProp + ' & ' +
                                          nextActProp + ')\n')

        # closing the formula
        adjFormula = adjFormula + "\t\t\t\t| ".join(adjSubFormulaArray)
        adjFormula = adjFormula + ' ) '

        adjFormulas.append(adjFormula)

    if onDebugMode:
        ltlmop_logger.debug(" & \n".join(adjFormulas))

    return " & \n".join(adjFormulas)
Example #17
0
def createAnzuFile(fileName, sensorList, robotPropList, adjData, spec):
    ''' This function writes the Anzu file. It encodes the specification and 
    topological relation. 
    It takes as input a filename, the list of the
    sensor propositions, the list of robot propositions (without the regions),
    the adjacency data (transition data structure) and
    a dictionary containing the specification strings.
    '''

    fileName = fileName + '.anzu'
    anzuFile = open(fileName, 'w')

    numBits = int(numpy.ceil(numpy.log2(len(adjData))))
    bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
    currBitEnc = bitEncode['current']
    nextBitEnc = bitEncode['next']
    
    # Write the header and begining of the formula
    anzuFile.write('[INPUT_VARIABLES]\n')
    anzuFile.writelines( "%s;\n" % item for item in sensorList )
    anzuFile.write('\n\n')


    anzuFile.write('[OUTPUT_VARIABLES]\n')
    anzuFile.writelines( "%s;\n" % item for item in robotPropList)
    anzuFile.write('\n\n')



    # Write the environment assumptions
    # from the 'spec' input 
    anzuFile.write('[ENV_INITIAL]\n')
    anzuFile.write(reformat(spec['EnvInit'], sensorList, robotPropList, numBits));
    anzuFile.write('\n\n')


    anzuFile.write('[ENV_TRANSITIONS]\n')
    anzuFile.write(reformat(spec['EnvTrans'], sensorList, robotPropList, numBits));
    anzuFile.write('\n\n')


    anzuFile.write('[ENV_FAIRNESS]\n')
    anzuFile.write(reformat(spec['EnvGoals']+')', sensorList, robotPropList, numBits))
    anzuFile.write(';\n\n')

    

    # Write the desired robot behavior
    anzuFile.write('[SYS_INITIAL]\n')
    anzuFile.write(reformat(spec['SysInit'], sensorList, robotPropList, numBits));
    anzuFile.write('\n\n')


    anzuFile.write('[SYS_TRANSITIONS]\n')
    # The topological relation (adjacency)
    for Origin in range(len(adjData)):
        # from region i we can stay in region i
        anzuFile.write('\t\t\t G( (')
        anzuFile.write(reformat(currBitEnc[Origin], sensorList, robotPropList, numBits))
        anzuFile.write(') -> ( (')
        anzuFile.write(reformat(nextBitEnc[Origin], sensorList, robotPropList, numBits))
        anzuFile.write(')')
        
        for dest in range(len(adjData)):
            if adjData[Origin][dest]:
                # not empty, hence there is a transition
                anzuFile.write('\n\t\t\t\t\t\t\t\t\t+ (')
                anzuFile.write(reformat(nextBitEnc[dest], sensorList, robotPropList, numBits))
                anzuFile.write(') ')

    # The rest of the system transitions
    anzuFile.write(reformat(spec['SysTrans'], sensorList, robotPropList, numBits));
    anzuFile.write('\n\n')


    anzuFile.write('[SYS_FAIRNESS]\n')
    anzuFile.write(reformat(spec['SysGoals'].strip()+')', sensorList, robotPropList, numBits))
    anzuFile.write(';\n\n')

    # close the file
    anzuFile.close()
Example #18
0
def createEnvTopologyFragmentNoHeading(adjData,
                                       regions,
                                       use_bits=True,
                                       other_robot_names_list=''):
    """
    other_robot_names_list: a tuple of names of robots around
    """
    if use_bits:
        numBits = int(math.ceil(math.log(len(adjData), 2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']

    # The topological relation (adjacency)
    adjFormulas = []

    if not other_robot_names_list:
        ltlmop_logger.info('robot_name not provided!')
        return

    for other_robot_name in other_robot_names_list:
        for Origin in range(len(adjData)):
            # skip boundary and obstacles
            if (regions[Origin].name == 'boundary'
                    or regions[Origin].isObstacle):
                continue
            """
            Obtain []( (robotName_regionProp1_rc & robotName_regionProp2)) -> (next(robotName_regionProp1_rc)|next(robotName_regionProp2_rc))
            """
            # from region i we can stay in region i
            adjFormula = '\t\t\t []( ('
            adjFormula = adjFormula + (currBitEnc[Origin] if use_bits else
                                       "e." + other_robot_name + '_' +
                                       regions[Origin].name)
            adjFormula = adjFormula + ') -> ( ('
            adjFormula = adjFormula + (nextBitEnc[Origin] if use_bits else
                                       "next(e." + other_robot_name + '_' +
                                       regions[Origin].name + ")")
            adjFormula = adjFormula + ')'

            for dest in range(len(adjData)):
                # skip boundary and obstacles
                if adjData[Origin][dest] and not (regions[dest].name
                                                  == 'boundary'
                                                  or regions[dest].isObstacle):
                    # not empty, hence there is a transition
                    adjFormula = adjFormula + '\n\t\t\t\t\t\t\t\t\t| ('
                    adjFormula = adjFormula + (
                        nextBitEnc[dest] if use_bits else "next(e." +
                        other_robot_name + '_' + regions[dest].name + ")")

                    adjFormula = adjFormula + ') '

            # closing this region
            adjFormula = adjFormula + ' ) ) '

            adjFormulas.append(adjFormula)
        """
        Obtain [](next(robotName_regionProp1) & ! next(robotName_regionProp2))|()|()
        """
        # In a BDD strategy, it's best to explicitly exclude these
        adjFormulas.append("[]" + createInitialEnvRegionFragment(
            regions, use_bits, True, other_robot_name))

    return " & \n".join(adjFormulas)
Example #19
0
    def _writeLTLFile(self):

        self.LTL2SpecLineNumber = None

        #regionList = [r.name for r in self.parser.proj.rfi.regions]
        regionList = [r.name for r in self.proj.rfi.regions]
        sensorList = deepcopy(self.proj.enabled_sensors)
        robotPropList = self.proj.enabled_actuators + self.proj.all_customs
        
        text = self.proj.specText

        response = None

        # Create LTL using selected parser
        # TODO: rename decomposition object to something other than 'parser'
        if self.proj.compile_options["parser"] == "slurp":
            # default to no region tags if no simconfig is defined, so we can compile without
            if self.proj.currentConfig is None:
                region_tags = {}
            else:
                region_tags = self.proj.currentConfig.region_tags
 
            # Hack: We need to make sure there's only one of these
            global _SLURP_SPEC_GENERATOR
            
            # Make a new specgenerator and have it process the text
            if not _SLURP_SPEC_GENERATOR:
                # Add SLURP to path for import
                p = os.path.dirname(os.path.abspath(__file__))
                sys.path.append(os.path.join(p, "..", "etc", "SLURP"))
                from ltlbroom.specgeneration import SpecGenerator
                _SLURP_SPEC_GENERATOR = SpecGenerator()
            
            # Filter out regions it shouldn't know about
            filtered_regions = [region.name for region in self.proj.rfi.regions 
                                if not (region.isObstacle or region.name.lower() == "boundary")]
            LTLspec_env, LTLspec_sys, self.proj.internal_props, internal_sensors, results, responses, traceback = \
                _SLURP_SPEC_GENERATOR.generate(text, sensorList, filtered_regions, robotPropList, region_tags)

            oldspec_env = LTLspec_env
            oldspec_sys = LTLspec_sys
 
            for ln, result in enumerate(results):
                if not result:
                    logging.warning("Could not parse the sentence in line {0}".format(ln))

            # Abort compilation if there were any errors
            if not all(results):
                return None, None, responses
        
            # Add in the sensors so they go into the SMV and spec files
            for s in internal_sensors:
                if s not in sensorList:
                    sensorList.append(s)
                    self.proj.all_sensors.append(s)
                    self.proj.enabled_sensors.append(s)                    

            # Conjoin all the spec chunks
            LTLspec_env = '\t\t' + ' & \n\t\t'.join(LTLspec_env)
            LTLspec_sys = '\t\t' + ' & \n\t\t'.join(LTLspec_sys)
            
            if self.proj.compile_options["decompose"]:
                # substitute decomposed region names
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        LTLspec_env = re.sub('\\bs\.' + r.name + '\\b', "("+' | '.join(["s."+x for x in self.parser.proj.regionMapping[r.name]])+")", LTLspec_env)
                        LTLspec_env = re.sub('\\be\.' + r.name + '\\b', "("+' | '.join(["e."+x for x in self.parser.proj.regionMapping[r.name]])+")", LTLspec_env)
                        LTLspec_sys = re.sub('\\bs\.' + r.name + '\\b', "("+' | '.join(["s."+x for x in self.parser.proj.regionMapping[r.name]])+")", LTLspec_sys)
                        LTLspec_sys = re.sub('\\be\.' + r.name + '\\b', "("+' | '.join(["e."+x for x in self.parser.proj.regionMapping[r.name]])+")", LTLspec_sys)

            response = responses

        elif self.proj.compile_options["parser"] == "ltl":
            # delete comments
            text = re.sub(r"#.*$", "", text, flags=re.MULTILINE)

            # split into env and sys parts (by looking for a line of just dashes in between)
            LTLspec_env, LTLspec_sys = re.split(r"^\s*-+\s*$", text, maxsplit=1, flags=re.MULTILINE)

            # split into subformulas
            LTLspec_env = re.split(r"(?:[ \t]*[\n\r][ \t]*)+", LTLspec_env)
            LTLspec_sys = re.split(r"(?:[ \t]*[\n\r][ \t]*)+", LTLspec_sys)

            # remove any empty initial entries (HACK?)
            while '' in LTLspec_env:
                LTLspec_env.remove('')
            while '' in LTLspec_sys:
                LTLspec_sys.remove('')

            # automatically conjoin all the subformulas
            LTLspec_env = '\t\t' + ' & \n\t\t'.join(LTLspec_env)
            LTLspec_sys = '\t\t' + ' & \n\t\t'.join(LTLspec_sys)

            if self.proj.compile_options["decompose"]:
                # substitute decomposed region 
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        LTLspec_env = re.sub('\\b(?:s\.)?' + r.name + '\\b', "("+' | '.join(["s."+x for x in self.parser.proj.regionMapping[r.name]])+")", LTLspec_env)
                        LTLspec_sys = re.sub('\\b(?:s\.)?' + r.name + '\\b', "("+' | '.join(["s."+x for x in self.parser.proj.regionMapping[r.name]])+")", LTLspec_sys)
            else:
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        LTLspec_env = re.sub('\\b(?:s\.)?' + r.name + '\\b', "s."+r.name, LTLspec_env)
                        LTLspec_sys = re.sub('\\b(?:s\.)?' + r.name + '\\b', "s."+r.name, LTLspec_sys)

            traceback = [] # HACK: needs to be something other than None
        elif self.proj.compile_options["parser"] == "structured":
            import parseEnglishToLTL

            if self.proj.compile_options["decompose"]:
                # substitute the regions name in specs
                for m in re.finditer(r'near (?P<rA>\w+)', text):
                    text=re.sub(r'near (?P<rA>\w+)', "("+' or '.join(["s."+r for r in self.parser.proj.regionMapping['near$'+m.group('rA')+'$'+str(50)]])+")", text)
                for m in re.finditer(r'within (?P<dist>\d+) (from|of) (?P<rA>\w+)', text):
                    text=re.sub(r'within ' + m.group('dist')+' (from|of) '+ m.group('rA'), "("+' or '.join(["s."+r for r in self.parser.proj.regionMapping['near$'+m.group('rA')+'$'+m.group('dist')]])+")", text)
                for m in re.finditer(r'between (?P<rA>\w+) and (?P<rB>\w+)', text):
                    text=re.sub(r'between ' + m.group('rA')+' and '+ m.group('rB'),"("+' or '.join(["s."+r for r in self.parser.proj.regionMapping['between$'+m.group('rA')+'$and$'+m.group('rB')+"$"]])+")", text)

                # substitute decomposed region 
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        text = re.sub('\\b' + r.name + '\\b', "("+' | '.join(["s."+x for x in self.parser.proj.regionMapping[r.name]])+")", text)

                regionList = ["s."+x.name for x in self.parser.proj.rfi.regions]
            else:
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        text = re.sub('\\b' + r.name + '\\b', "s."+r.name, text)

                regionList = ["s."+x.name for x in self.proj.rfi.regions]

            spec, traceback, failed, self.LTL2SpecLineNumber, self.proj.internal_props = parseEnglishToLTL.writeSpec(text, sensorList, regionList, robotPropList)

            # Abort compilation if there were any errors
            if failed:
                return None, None, None

            LTLspec_env = spec["EnvInit"] + spec["EnvTrans"] + spec["EnvGoals"]
            LTLspec_sys = spec["SysInit"] + spec["SysTrans"] + spec["SysGoals"]

        else:
            logging.error("Parser type '{0}' not currently supported".format(self.proj.compile_options["parser"]))
            return None, None, None

        if self.proj.compile_options["decompose"]:
            regionList = [x.name for x in self.parser.proj.rfi.regions]
        else:
            regionList = [x.name for x in self.proj.rfi.regions]

        if self.proj.compile_options["use_region_bit_encoding"]:
            # Define the number of bits needed to encode the regions
            numBits = int(math.ceil(math.log(len(regionList),2)))

            # creating the region bit encoding
            bitEncode = bitEncoding(len(regionList),numBits)
            currBitEnc = bitEncode['current']
            nextBitEnc = bitEncode['next']

            # switch to bit encodings for regions
            LTLspec_env = replaceRegionName(LTLspec_env, bitEncode, regionList)
            LTLspec_sys = replaceRegionName(LTLspec_sys, bitEncode, regionList)
        
            if self.LTL2SpecLineNumber is not None:
                for k in self.LTL2SpecLineNumber.keys():
                    new_k = replaceRegionName(k, bitEncode, regionList)
                    if new_k != k:
                        self.LTL2SpecLineNumber[new_k] = self.LTL2SpecLineNumber[k]
                        del self.LTL2SpecLineNumber[k]

        if self.proj.compile_options["decompose"]:
            adjData = self.parser.proj.rfi.transitions
        else:
            adjData = self.proj.rfi.transitions

        # Store some data needed for later analysis
        self.spec = {}
        if self.proj.compile_options["decompose"]:
            self.spec['Topo'] = createTopologyFragment(adjData, self.parser.proj.rfi.regions, use_bits=self.proj.compile_options["use_region_bit_encoding"])
        else: 
            self.spec['Topo'] = createTopologyFragment(adjData, self.proj.rfi.regions, use_bits=self.proj.compile_options["use_region_bit_encoding"])

        # Substitute any macros that the parsers passed us
        LTLspec_env = self.substituteMacros(LTLspec_env)
        LTLspec_sys = self.substituteMacros(LTLspec_sys)

        # If we are not using bit-encoding, we need to
        # explicitly encode a mutex for regions
        if not self.proj.compile_options["use_region_bit_encoding"]:
            # DNF version (extremely slow for core-finding)
            #mutex = "\n\t&\n\t []({})".format(" | ".join(["({})".format(" & ".join(["s."+r2.name if r is r2 else "!s."+r2.name for r2 in self.parser.proj.rfi.regions])) for r in self.parser.proj.rfi.regions]))

            if self.proj.compile_options["decompose"]:
                region_list = self.parser.proj.rfi.regions
            else:
                region_list = self.proj.rfi.regions

            # Almost-CNF version
            exclusions = []
            for i, r1 in enumerate(region_list):
                for r2 in region_list[i+1:]:
                    exclusions.append("!(s.{} & s.{})".format(r1.name, r2.name))
            mutex = "\n&\n\t []({})".format(" & ".join(exclusions))
            LTLspec_sys += mutex

        self.spec.update(self.splitSpecIntoComponents(LTLspec_env, LTLspec_sys))

        # Add in a fragment to make sure that we start in a valid region
        if self.proj.compile_options["decompose"]:
            self.spec['InitRegionSanityCheck'] = createInitialRegionFragment(self.parser.proj.rfi.regions, use_bits=self.proj.compile_options["use_region_bit_encoding"])
        else:
            self.spec['InitRegionSanityCheck'] = createInitialRegionFragment(self.proj.rfi.regions, use_bits=self.proj.compile_options["use_region_bit_encoding"])
        LTLspec_sys += "\n&\n" + self.spec['InitRegionSanityCheck']

        LTLspec_sys += "\n&\n" + self.spec['Topo']

        createLTLfile(self.proj.getFilenamePrefix(), LTLspec_env, LTLspec_sys)
        
        if self.proj.compile_options["parser"] == "slurp":
            self.reversemapping = {self.postprocessLTL(line,sensorList,robotPropList).strip():line.strip() for line in oldspec_env + oldspec_sys}
            self.reversemapping[self.spec['Topo'].replace("\n","").replace("\t","").lstrip().rstrip("\n\t &")] = "TOPOLOGY"

        #for k,v in self.reversemapping.iteritems():
        #    print "{!r}:{!r}".format(k,v)        

        return self.spec, traceback, response
Example #20
0
def createAnzuFile(fileName, sensorList, robotPropList, adjData, spec):
    ''' This function writes the Anzu file. It encodes the specification and 
    topological relation. 
    It takes as input a filename, the list of the
    sensor propositions, the list of robot propositions (without the regions),
    the adjacency data (transition data structure) and
    a dictionary containing the specification strings.
    '''

    fileName = fileName + '.anzu'
    anzuFile = open(fileName, 'w')

    numBits = int(numpy.ceil(numpy.log2(len(adjData))))
    bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
    currBitEnc = bitEncode['current']
    nextBitEnc = bitEncode['next']

    # Write the header and begining of the formula
    anzuFile.write('[INPUT_VARIABLES]\n')
    anzuFile.writelines("%s;\n" % item for item in sensorList)
    anzuFile.write('\n\n')

    anzuFile.write('[OUTPUT_VARIABLES]\n')
    anzuFile.writelines("%s;\n" % item for item in robotPropList)
    anzuFile.write('\n\n')

    # Write the environment assumptions
    # from the 'spec' input
    anzuFile.write('[ENV_INITIAL]\n')
    anzuFile.write(
        reformat(spec['EnvInit'], sensorList, robotPropList, numBits))
    anzuFile.write('\n\n')

    anzuFile.write('[ENV_TRANSITIONS]\n')
    anzuFile.write(
        reformat(spec['EnvTrans'], sensorList, robotPropList, numBits))
    anzuFile.write('\n\n')

    anzuFile.write('[ENV_FAIRNESS]\n')
    anzuFile.write(
        reformat(spec['EnvGoals'] + ')', sensorList, robotPropList, numBits))
    anzuFile.write(';\n\n')

    # Write the desired robot behavior
    anzuFile.write('[SYS_INITIAL]\n')
    anzuFile.write(
        reformat(spec['SysInit'], sensorList, robotPropList, numBits))
    anzuFile.write('\n\n')

    anzuFile.write('[SYS_TRANSITIONS]\n')
    # The topological relation (adjacency)
    for Origin in range(len(adjData)):
        # from region i we can stay in region i
        anzuFile.write('\t\t\t G( (')
        anzuFile.write(
            reformat(currBitEnc[Origin], sensorList, robotPropList, numBits))
        anzuFile.write(') -> ( (')
        anzuFile.write(
            reformat(nextBitEnc[Origin], sensorList, robotPropList, numBits))
        anzuFile.write(')')

        for dest in range(len(adjData)):
            if adjData[Origin][dest]:
                # not empty, hence there is a transition
                anzuFile.write('\n\t\t\t\t\t\t\t\t\t+ (')
                anzuFile.write(
                    reformat(nextBitEnc[dest], sensorList, robotPropList,
                             numBits))
                anzuFile.write(') ')

    # The rest of the system transitions
    anzuFile.write(
        reformat(spec['SysTrans'], sensorList, robotPropList, numBits))
    anzuFile.write('\n\n')

    anzuFile.write('[SYS_FAIRNESS]\n')
    anzuFile.write(
        reformat(spec['SysGoals'].strip() + ')', sensorList, robotPropList,
                 numBits))
    anzuFile.write(';\n\n')

    # close the file
    anzuFile.close()
Example #21
0
def createLTLfile(fileName, sensorList, robotPropList, adjData, spec):
    ''' This function writes the LTL file. It encodes the specification and 
    topological relation. 
    It takes as input a filename, the list of the
    sensor propositions, the list of robot propositions (without the regions),
    the adjacency data (transition data structure) and
    a dictionary containing the specification strings.
    '''

    fileName = fileName + '.ltl'
    ltlFile = open(fileName, 'w')

    numBits = int(numpy.ceil(numpy.log2(len(adjData))))
    bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
    currBitEnc = bitEncode['current']
    nextBitEnc = bitEncode['next']

    # Write the header and begining of the formula
    ltlFile.write(
        textwrap.dedent("""
    -- LTL specification file
    -- (Generated by the LTLMoP toolkit)

    """))
    ltlFile.write('LTLSPEC -- Assumptions\n')
    ltlFile.write('\t(\n')

    # Write the environment assumptions
    # from the 'spec' input
    ltlFile.write(spec['EnvInit'])
    ltlFile.write(spec['EnvTrans'])
    ltlFile.write(spec['EnvGoals'])
    ltlFile.write('\n\t);\n\n')

    ltlFile.write('LTLSPEC -- Guarantees\n')
    ltlFile.write('\t(\n')

    # Write the desired robot behavior
    ltlFile.write(spec['SysInit'])

    # The topological relation (adjacency)
    for Origin in range(len(adjData)):
        # from region i we can stay in region i
        ltlFile.write('\t\t\t []( (')
        ltlFile.write(currBitEnc[Origin])
        ltlFile.write(') -> ( (')
        ltlFile.write(nextBitEnc[Origin])
        ltlFile.write(')')

        for dest in range(len(adjData)):
            if adjData[Origin][dest]:
                # not empty, hence there is a transition
                ltlFile.write('\n\t\t\t\t\t\t\t\t\t| (')
                ltlFile.write(nextBitEnc[dest])
                ltlFile.write(') ')

        # closing this region
        ltlFile.write(' ) ) & \n ')

    # The rest of the spec
    ltlFile.write(spec['SysTrans'])
    ltlFile.write(spec['SysGoals'])
    # Close the LTL formula
    ltlFile.write('\n\t);\n')

    # close the file
    ltlFile.close()
Example #22
0
def createIASysTopologyFragment(adjData, regions, use_bits=True):
    """
    Obtain []( next(regionProp1_rc) -> (next(regionProp1) | next(regionProp2))
    """
    if use_bits:
        numBits = int(math.ceil(math.log(len(adjData), 2)))
        # TODO: only calc bitencoding once
        bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
        currBitEnc = bitEncode['current']
        nextBitEnc = bitEncode['next']
        envBitEnc = bitEncode['env']
        envNextBitEnc = bitEncode['envNext']

    # The topological relation (adjacency)
    adjFormulas = []

    for Origin in range(len(adjData)):
        if (regions[Origin].name == 'boundary' or regions[Origin].isObstacle):
            continue
        # from region i we can stay in region i
        adjFormula = '\t\t\t []( ('
        adjFormula = adjFormula + (envNextBitEnc[Origin] if use_bits else
                                   "next(e." + regions[Origin].name + "_rc)")
        adjFormula = adjFormula + ') -> ( ('
        adjFormula = adjFormula + (nextBitEnc[Origin] if use_bits else
                                   "next(s." + regions[Origin].name + ")")

        adjFormula = adjFormula + ')'

        for dest in range(len(adjData)):
            if regions[dest].name == 'boundary' or regions[dest].isObstacle:
                continue

            if adjData[Origin][dest]:
                # not empty, hence there is a transition
                adjFormula = adjFormula + ' | ('
                adjFormula = adjFormula + (nextBitEnc[dest]
                                           if use_bits else "next(s." +
                                           regions[dest].name + ")")
                adjFormula = adjFormula + ') '

        # closing this region
        adjFormula = adjFormula + ' ) ) '

        adjFormulas.append(adjFormula)

    if onDebugMode:
        ltlmop_logger.debug(
            "[]( next(regionProp1_rc) -> (next(regionProp1) | next(regionProp2))"
        )
        ltlmop_logger.debug(adjFormulas)
    """
    []regionProp1' -> ! (regionProp2' | regionProp3' | regionProp4')
    """
    for Origin in range(len(adjData)):
        if regions[Origin].name == 'boundary' or regions[Origin].isObstacle:
            continue

        # from region i we can stay in region i
        adjFormula = '\t\t\t []( ('
        adjFormula = adjFormula + (nextBitEnc[Origin] if use_bits else
                                   "next(s." + regions[Origin].name + ")")
        adjFormula = adjFormula + ') -> ! ( '
        regProps = []
        for Others in range(len(adjData)):
            if regions[Others].name == 'boundary' or regions[Others].isObstacle:
                continue

            if not regions[Origin].name == regions[Others].name:
                # not empty, hence there is a transition
                regProps.append(nextBitEnc[Others] if use_bits else "next(s." +
                                regions[Others].name + ")")

        adjFormula = adjFormula + " | ".join(regProps)
        # closing this region
        adjFormula = adjFormula + ' ) ) '

        adjFormulas.append(adjFormula)

    if onDebugMode:
        ltlmop_logger.debug(
            "[]regionProp1' -> ! (regionProp2' | regionProp3' | regionProp4')")
        ltlmop_logger.debug(adjFormula)
    """
    [] regionProp1' | regionProp2' | regionProp3'
    """

    # In a BDD strategy, it's best to explicitly exclude these
    adjFormulas.append("[]" + createInitialRegionFragment(regions, use_bits))

    if onDebugMode:
        ltlmop_logger.debug("[] regionProp1' | regionProp2' | regionProp3'")
        ltlmop_logger.debug("[]" +
                            createInitialRegionFragment(regions, use_bits))

    return " & \n".join(adjFormulas)
Example #23
0
    def _writeLTLFile(self):

        self.LTL2SpecLineNumber = None

        #regionList = [r.name for r in self.parser.proj.rfi.regions]
        regionList = [r.name for r in self.proj.rfi.regions]
        sensorList = deepcopy(self.proj.enabled_sensors)
        robotPropList = self.proj.enabled_actuators + self.proj.all_customs

        text = self.proj.specText

        response = None

        # Create LTL using selected parser
        # TODO: rename decomposition object to something other than 'parser'
        if self.proj.compile_options["parser"] == "slurp":
            # default to no region tags if no simconfig is defined, so we can compile without
            if self.proj.current_config == "":
                region_tags = {}
            else:
                self.hsub = handlerSubsystem.HandlerSubsystem(
                    None, self.proj.project_root)
                config, success = self.hsub.loadConfigFile(
                    self.proj.current_config)
                if success: self.hsub.configs.append(config)
                self.hsub.setExecutingConfig(self.proj.current_config)

                region_tags = self.hsub.executing_config.region_tags

            # Hack: We need to make sure there's only one of these
            global _SLURP_SPEC_GENERATOR

            # Make a new specgenerator and have it process the text
            if not _SLURP_SPEC_GENERATOR:
                # Add SLURP to path for import
                p = os.path.dirname(os.path.abspath(__file__))
                sys.path.append(os.path.join(p, "..", "etc", "SLURP"))
                from ltlbroom.specgeneration import SpecGenerator
                _SLURP_SPEC_GENERATOR = SpecGenerator()

            # Filter out regions it shouldn't know about
            filtered_regions = [
                region.name for region in self.proj.rfi.regions
                if not (region.isObstacle or region.name.lower() == "boundary")
            ]
            LTLspec_env, LTLspec_sys, self.proj.internal_props, internal_sensors, results, responses, traceback = \
                _SLURP_SPEC_GENERATOR.generate(text, sensorList, filtered_regions, robotPropList, region_tags)

            oldspec_env = LTLspec_env
            oldspec_sys = LTLspec_sys

            for ln, result in enumerate(results):
                if not result:
                    logging.warning(
                        "Could not parse the sentence in line {0}".format(ln))

            # Abort compilation if there were any errors
            if not all(results):
                return None, None, responses

            # Add in the sensors so they go into the SMV and spec files
            for s in internal_sensors:
                if s not in sensorList:
                    sensorList.append(s)
                    self.proj.all_sensors.append(s)
                    self.proj.enabled_sensors.append(s)

            # Conjoin all the spec chunks
            LTLspec_env = '\t\t' + ' & \n\t\t'.join(LTLspec_env)
            LTLspec_sys = '\t\t' + ' & \n\t\t'.join(LTLspec_sys)

            if self.proj.compile_options["decompose"]:
                # substitute decomposed region names
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        LTLspec_env = re.sub(
                            '\\bs\.' + r.name + '\\b', "(" + ' | '.join([
                                "s." + x
                                for x in self.parser.proj.regionMapping[r.name]
                            ]) + ")", LTLspec_env)
                        LTLspec_env = re.sub(
                            '\\be\.' + r.name + '\\b', "(" + ' | '.join([
                                "e." + x
                                for x in self.parser.proj.regionMapping[r.name]
                            ]) + ")", LTLspec_env)
                        LTLspec_sys = re.sub(
                            '\\bs\.' + r.name + '\\b', "(" + ' | '.join([
                                "s." + x
                                for x in self.parser.proj.regionMapping[r.name]
                            ]) + ")", LTLspec_sys)
                        LTLspec_sys = re.sub(
                            '\\be\.' + r.name + '\\b', "(" + ' | '.join([
                                "e." + x
                                for x in self.parser.proj.regionMapping[r.name]
                            ]) + ")", LTLspec_sys)

            response = responses

        elif self.proj.compile_options["parser"] == "ltl":
            # delete comments
            text = re.sub(r"#.*$", "", text, flags=re.MULTILINE)

            # split into env and sys parts (by looking for a line of just dashes in between)
            LTLspec_env, LTLspec_sys = re.split(r"^\s*-+\s*$",
                                                text,
                                                maxsplit=1,
                                                flags=re.MULTILINE)

            # split into subformulas
            LTLspec_env = re.split(r"(?:[ \t]*[\n\r][ \t]*)+", LTLspec_env)
            LTLspec_sys = re.split(r"(?:[ \t]*[\n\r][ \t]*)+", LTLspec_sys)

            # remove any empty initial entries (HACK?)
            while '' in LTLspec_env:
                LTLspec_env.remove('')
            while '' in LTLspec_sys:
                LTLspec_sys.remove('')

            # automatically conjoin all the subformulas
            LTLspec_env = '\t\t' + ' & \n\t\t'.join(LTLspec_env)
            LTLspec_sys = '\t\t' + ' & \n\t\t'.join(LTLspec_sys)

            if self.proj.compile_options["decompose"]:
                # substitute decomposed region
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        LTLspec_env = re.sub(
                            '\\b(?:s\.)?' + r.name + '\\b', "(" + ' | '.join([
                                "s." + x
                                for x in self.parser.proj.regionMapping[r.name]
                            ]) + ")", LTLspec_env)
                        LTLspec_sys = re.sub(
                            '\\b(?:s\.)?' + r.name + '\\b', "(" + ' | '.join([
                                "s." + x
                                for x in self.parser.proj.regionMapping[r.name]
                            ]) + ")", LTLspec_sys)
            else:
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        LTLspec_env = re.sub('\\b(?:s\.)?' + r.name + '\\b',
                                             "s." + r.name, LTLspec_env)
                        LTLspec_sys = re.sub('\\b(?:s\.)?' + r.name + '\\b',
                                             "s." + r.name, LTLspec_sys)

            traceback = []  # HACK: needs to be something other than None
        elif self.proj.compile_options["parser"] == "structured":
            import parseEnglishToLTL

            if self.proj.compile_options["decompose"]:
                # substitute the regions name in specs
                for m in re.finditer(r'near (?P<rA>\w+)', text):
                    text = re.sub(
                        r'near (?P<rA>\w+)', "(" + ' or '.join([
                            "s." + r for r in self.parser.proj.regionMapping[
                                'near$' + m.group('rA') + '$' + str(50)]
                        ]) + ")", text)
                for m in re.finditer(
                        r'within (?P<dist>\d+) (from|of) (?P<rA>\w+)', text):
                    text = re.sub(
                        r'within ' + m.group('dist') + ' (from|of) ' +
                        m.group('rA'), "(" + ' or '.join([
                            "s." + r for r in self.parser.proj.regionMapping[
                                'near$' + m.group('rA') + '$' +
                                m.group('dist')]
                        ]) + ")", text)
                for m in re.finditer(r'between (?P<rA>\w+) and (?P<rB>\w+)',
                                     text):
                    text = re.sub(
                        r'between ' + m.group('rA') + ' and ' + m.group('rB'),
                        "(" + ' or '.join([
                            "s." + r for r in self.parser.proj.regionMapping[
                                'between$' + m.group('rA') + '$and$' +
                                m.group('rB') + "$"]
                        ]) + ")", text)

                # substitute decomposed region
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        text = re.sub(
                            '\\b' + r.name + '\\b', "(" + ' | '.join([
                                "s." + x
                                for x in self.parser.proj.regionMapping[r.name]
                            ]) + ")", text)

                regionList = [
                    "s." + x.name for x in self.parser.proj.rfi.regions
                ]
            else:
                for r in self.proj.rfi.regions:
                    if not (r.isObstacle or r.name.lower() == "boundary"):
                        text = re.sub('\\b' + r.name + '\\b', "s." + r.name,
                                      text)

                regionList = ["s." + x.name for x in self.proj.rfi.regions]

            spec, traceback, failed, self.LTL2SpecLineNumber, self.proj.internal_props = parseEnglishToLTL.writeSpec(
                text, sensorList, regionList, robotPropList)

            # Abort compilation if there were any errors
            if failed:
                return None, None, None

            LTLspec_env = spec["EnvInit"] + spec["EnvTrans"] + spec["EnvGoals"]
            LTLspec_sys = spec["SysInit"] + spec["SysTrans"] + spec["SysGoals"]

        else:
            logging.error("Parser type '{0}' not currently supported".format(
                self.proj.compile_options["parser"]))
            return None, None, None

        if self.proj.compile_options["decompose"]:
            regionList = [x.name for x in self.parser.proj.rfi.regions]
        else:
            regionList = [x.name for x in self.proj.rfi.regions]

        if self.proj.compile_options["use_region_bit_encoding"]:
            # Define the number of bits needed to encode the regions
            numBits = int(math.ceil(math.log(len(regionList), 2)))

            # creating the region bit encoding
            bitEncode = bitEncoding(len(regionList), numBits)
            currBitEnc = bitEncode['current']
            nextBitEnc = bitEncode['next']

            # switch to bit encodings for regions
            LTLspec_env = replaceRegionName(LTLspec_env, bitEncode, regionList)
            LTLspec_sys = replaceRegionName(LTLspec_sys, bitEncode, regionList)

            if self.LTL2SpecLineNumber is not None:
                for k in self.LTL2SpecLineNumber.keys():
                    new_k = replaceRegionName(k, bitEncode, regionList)
                    if new_k != k:
                        self.LTL2SpecLineNumber[
                            new_k] = self.LTL2SpecLineNumber[k]
                        del self.LTL2SpecLineNumber[k]

        if self.proj.compile_options["decompose"]:
            adjData = self.parser.proj.rfi.transitions
        else:
            adjData = self.proj.rfi.transitions

        # Store some data needed for later analysis
        self.spec = {}
        if self.proj.compile_options["decompose"]:
            self.spec['Topo'] = createTopologyFragment(
                adjData,
                self.parser.proj.rfi.regions,
                use_bits=self.proj.compile_options["use_region_bit_encoding"])
        else:
            self.spec['Topo'] = createTopologyFragment(
                adjData,
                self.proj.rfi.regions,
                use_bits=self.proj.compile_options["use_region_bit_encoding"])

        # Substitute any macros that the parsers passed us
        LTLspec_env = self.substituteMacros(LTLspec_env)
        LTLspec_sys = self.substituteMacros(LTLspec_sys)

        # If we are not using bit-encoding, we need to
        # explicitly encode a mutex for regions
        if not self.proj.compile_options["use_region_bit_encoding"]:
            # DNF version (extremely slow for core-finding)
            #mutex = "\n\t&\n\t []({})".format(" | ".join(["({})".format(" & ".join(["s."+r2.name if r is r2 else "!s."+r2.name for r2 in self.parser.proj.rfi.regions])) for r in self.parser.proj.rfi.regions]))

            if self.proj.compile_options["decompose"]:
                region_list = self.parser.proj.rfi.regions
            else:
                region_list = self.proj.rfi.regions

            # Almost-CNF version
            exclusions = []
            for i, r1 in enumerate(region_list):
                for r2 in region_list[i + 1:]:
                    exclusions.append("!(s.{} & s.{})".format(
                        r1.name, r2.name))
            mutex = "\n&\n\t []({})".format(" & ".join(exclusions))
            LTLspec_sys += mutex

        self.spec.update(self.splitSpecIntoComponents(LTLspec_env,
                                                      LTLspec_sys))

        # Add in a fragment to make sure that we start in a valid region
        if self.proj.compile_options["decompose"]:
            self.spec['InitRegionSanityCheck'] = createInitialRegionFragment(
                self.parser.proj.rfi.regions,
                use_bits=self.proj.compile_options["use_region_bit_encoding"])
        else:
            self.spec['InitRegionSanityCheck'] = createInitialRegionFragment(
                self.proj.rfi.regions,
                use_bits=self.proj.compile_options["use_region_bit_encoding"])
        LTLspec_sys += "\n&\n" + self.spec['InitRegionSanityCheck']

        LTLspec_sys += "\n&\n" + self.spec['Topo']

        createLTLfile(self.proj.getFilenamePrefix(), LTLspec_env, LTLspec_sys)

        if self.proj.compile_options["parser"] == "slurp":
            self.reversemapping = {
                self.postprocessLTL(line, sensorList, robotPropList).strip():
                line.strip()
                for line in oldspec_env + oldspec_sys
            }
            self.reversemapping[self.spec['Topo'].replace("\n", "").replace(
                "\t", "").lstrip().rstrip("\n\t &")] = "TOPOLOGY"

        #for k,v in self.reversemapping.iteritems():
        #    print "{!r}:{!r}".format(k,v)

        return self.spec, traceback, response
Example #24
0
def createIAEnvTopologyFragment(adjData, regions, actuatorList, use_bits=True):
    """
    Obtain []( (regionProp1_rc & regionProp1) -> (next(regionProp1_rc)))
    """
    # The topological relation (adjacency)
    adjFormulas = []
    if regions:
        if use_bits:
            numBits = int(math.ceil(math.log(len(adjData), 2)))
            # TODO: only calc bitencoding once
            bitEncode = parseEnglishToLTL.bitEncoding(len(adjData), numBits)
            currBitEnc = bitEncode['current']
            nextBitEnc = bitEncode['next']
            envBitEnc = bitEncode['env']
            envNextBitEnc = bitEncode['envNext']

        for Origin in range(len(adjData)):
            if regions[Origin].name == 'boundary' or regions[Origin].isObstacle:
                continue

            # from region i we can stay in region i
            adjFormula = '\t\t\t []( ('
            adjFormula = adjFormula + (envBitEnc[Origin] if use_bits else
                                       "e." + regions[Origin].name + "_rc")
            adjFormula = adjFormula + ' & '
            adjFormula = adjFormula + (currBitEnc[Origin] if use_bits else
                                       "s." + regions[Origin].name)

            adjFormula = adjFormula + ') -> ('

            adjFormula = adjFormula + (envNextBitEnc[Origin]
                                       if use_bits else "next(e." +
                                       regions[Origin].name + "_rc)")
            adjFormula = adjFormula + ") ) "

            adjFormulas.append(adjFormula)

        if onDebugMode:
            ltlmop_logger.debug(
                "[]( (regionProp1_rc & regionProp1) -> (next(regionProp1_rc)))"
            )
            ltlmop_logger.debug(adjFormulas)
        """
        Obtain []( (regionProp1_rc & regionProp2)) -> (next(regionProp1_rc)|next(regionProp2_rc))
        """
        for Origin in range(len(adjData)):
            if regions[Origin].name == 'boundary' or regions[Origin].isObstacle:
                continue

            for dest in range(len(adjData)):
                if regions[dest].name == 'boundary' or regions[dest].isObstacle:
                    continue

                if adjData[Origin][dest]:
                    # from region i we can head to dest stay in Origin
                    adjFormula = '\t\t\t []( ('
                    adjFormula = adjFormula + (envBitEnc[Origin]
                                               if use_bits else "e." +
                                               regions[Origin].name + "_rc")
                    adjFormula = adjFormula + ' & '
                    adjFormula = adjFormula + (currBitEnc[dest] if use_bits
                                               else "s." + regions[dest].name)
                    adjFormula = adjFormula + ') -> ('
                    # still in the current region
                    adjFormula = adjFormula + (envNextBitEnc[Origin]
                                               if use_bits else "next(e." +
                                               regions[Origin].name + "_rc)")

                    # not empty, hence there is a transition
                    adjFormula = adjFormula + ' | '
                    adjFormula = adjFormula + (envNextBitEnc[dest]
                                               if use_bits else "next(e." +
                                               regions[dest].name + "_rc)")
                    adjFormula = adjFormula + ') )'
                    adjFormulas.append(adjFormula)

        if onDebugMode:
            ltlmop_logger.debug(
                "[]( (regionProp1_rc & regionProp2)) -> (next(regionProp1_rc)|next(regionProp2_rc))"
            )
            ltlmop_logger.debug(adjFormula)
        """
        []regionProp1_rc' <-> ! (regionProp2_rc' | regionProp3_rc' | regionProp4_rc')
        """
        for Origin in range(len(adjData)):
            if (regions[Origin].name == 'boundary'
                    or regions[Origin].isObstacle):
                continue

            # from region i we can stay in region i
            adjFormula = '\t\t\t []( ('
            adjFormula = adjFormula + (envNextBitEnc[Origin]
                                       if use_bits else "next(e." +
                                       regions[Origin].name + "_rc)")
            adjFormula = adjFormula + ') <-> ! ( '
            regPropRCs = []
            for Others in range(len(adjData)):
                if regions[Others].name == 'boundary' or regions[
                        Others].isObstacle:
                    continue

                if not regions[Origin].name == regions[Others].name:
                    # not empty, hence there is a transition
                    regPropRCs.append(
                        envNextBitEnc[Others] if use_bits else "next(e." +
                        regions[Others].name + "_rc)")

            adjFormula = adjFormula + " | ".join(regPropRCs)
            adjFormula = adjFormula + ") ) "
            adjFormulas.append(adjFormula)

            if onDebugMode:
                ltlmop_logger.debug(
                    "[]regionProp1_rc' -> ! (regionProp2_rc' | regionProp3_rc' | regionProp4_rc')"
                )
                ltlmop_logger.debug(adjFormula)
    """
    [] regionProp1' | regionProp2' | regionProp3'
    """
    if regions:
        # In a BDD strategy, it's best to explicitly exclude these
        adjFormulas.append(
            "\t\t\t []" +
            createIAInitialEnvRegionFragment(regions, use_bits, True))

        if onDebugMode:
            ltlmop_logger.debug(
                "[] regionProp1' | regionProp2' | regionProp3'")
            ltlmop_logger.debug(
                "[]" +
                createIAInitialEnvRegionFragment(regions, use_bits, True))

    return " & \n".join(adjFormulas)