Exemplo n.º 1
0
    def testCompute(self):
        tm = ExtendedTemporalMemory(columnDimensions=[4],
                                    cellsPerColumn=10,
                                    learnOnOneCell=False,
                                    initialPermanence=0.2,
                                    connectedPermanence=0.7,
                                    activationThreshold=1)

        seg1 = tm.connections.createSegment(0)
        seg2 = tm.connections.createSegment(20)
        seg3 = tm.connections.createSegment(25)
        try:
            tm.connections.createSynapse(seg1, 15, 0.9)
            tm.connections.createSynapse(seg2, 35, 0.9)
            tm.connections.createSynapse(seg2, 45, 0.9)  # external cell
            tm.connections.createSynapse(seg3, 35, 0.9)
            tm.connections.createSynapse(seg3, 50, 0.9)  # external cell
        except IndexError:
            self.fail("IndexError raised unexpectedly for distal segments")

        aSeg1 = tm.apicalConnections.createSegment(1)
        aSeg2 = tm.apicalConnections.createSegment(25)
        try:
            tm.apicalConnections.createSynapse(aSeg1, 3, 0.9)
            tm.apicalConnections.createSynapse(aSeg2, 1, 0.9)
        except IndexError:
            self.fail("IndexError raised unexpectedly for apical segments")

        activeColumns = set([1, 3])
        activeExternalCells = set([5, 10, 15])
        activeApicalCells = set([1, 2, 3, 4])

        tm.compute(activeColumns,
                   activeExternalCells=activeExternalCells,
                   activeApicalCells=activeApicalCells,
                   learn=False)

        activeColumns = set([0, 2])
        tm.compute(activeColumns,
                   activeExternalCells=set(),
                   activeApicalCells=set())

        self.assertEqual(tm.activeCells, set([0, 20, 25]))
Exemplo n.º 2
0
    def testCompute(self):
        tm = ExtendedTemporalMemory(
            columnDimensions=[4],
            cellsPerColumn=10,
            learnOnOneCell=False,
            initialPermanence=0.2,
            connectedPermanence=0.7,
            activationThreshold=1,
        )

        seg1 = tm.connections.createSegment(0)
        seg2 = tm.connections.createSegment(20)
        seg3 = tm.connections.createSegment(25)
        try:
            tm.connections.createSynapse(seg1, 15, 0.9)
            tm.connections.createSynapse(seg2, 35, 0.9)
            tm.connections.createSynapse(seg2, 45, 0.9)  # external cell
            tm.connections.createSynapse(seg3, 35, 0.9)
            tm.connections.createSynapse(seg3, 50, 0.9)  # external cell
        except IndexError:
            self.fail("IndexError raised unexpectedly for distal segments")

        aSeg1 = tm.apicalConnections.createSegment(1)
        aSeg2 = tm.apicalConnections.createSegment(25)
        try:
            tm.apicalConnections.createSynapse(aSeg1, 3, 0.9)
            tm.apicalConnections.createSynapse(aSeg2, 1, 0.9)
        except IndexError:
            self.fail("IndexError raised unexpectedly for apical segments")

        activeColumns = set([1, 3])
        activeExternalCells = set([5, 10, 15])
        activeApicalCells = set([1, 2, 3, 4])

        tm.compute(
            activeColumns, activeExternalCells=activeExternalCells, activeApicalCells=activeApicalCells, learn=False
        )

        activeColumns = set([0, 2])
        tm.compute(activeColumns, activeExternalCells=set(), activeApicalCells=set())

        self.assertEqual(tm.activeCells, set([0, 20, 25]))
Exemplo n.º 3
0
    def testWriteRead(self):
        tm1 = ExtendedTemporalMemory(
            columnDimensions=[100],
            cellsPerColumn=4,
            activationThreshold=7,
            initialPermanence=0.37,
            connectedPermanence=0.58,
            minThreshold=4,
            maxNewSynapseCount=18,
            permanenceIncrement=0.23,
            permanenceDecrement=0.08,
            seed=91,
        )

        # Run some data through before serializing
        self.patternMachine = PatternMachine(100, 4)
        self.sequenceMachine = SequenceMachine(self.patternMachine)
        sequence = self.sequenceMachine.generateFromNumbers(range(5))
        for _ in range(3):
            for pattern in sequence:
                tm1.compute(pattern)

        proto1 = TemporalMemoryProto_capnp.TemporalMemoryProto.new_message()
        tm1.write(proto1)

        # Write the proto to a temp file and read it back into a new proto
        with tempfile.TemporaryFile() as f:
            proto1.write(f)
            f.seek(0)
            proto2 = TemporalMemoryProto_capnp.TemporalMemoryProto.read(f)

        # Load the deserialized proto
        tm2 = ExtendedTemporalMemory.read(proto2)

        # Check that the two temporal memory objects have the same attributes
        self.assertEqual(tm1, tm2)

        # Run a couple records through after deserializing and check results match
        tm1.compute(self.patternMachine.get(0))
        tm2.compute(self.patternMachine.get(0))
        self.assertEqual(set(tm1.getActiveCells()), set(tm2.getActiveCells()))
        self.assertEqual(set(tm1.getPredictiveCells()), set(tm2.getPredictiveCells()))
        self.assertEqual(set(tm1.getWinnerCells()), set(tm2.getWinnerCells()))
        self.assertEqual(tm1.connections, tm2.connections)

        tm1.compute(self.patternMachine.get(3))
        tm2.compute(self.patternMachine.get(3))
        self.assertEqual(set(tm1.getActiveCells()), set(tm2.getActiveCells()))
        self.assertEqual(set(tm1.getPredictiveCells()), set(tm2.getPredictiveCells()))
        self.assertEqual(set(tm1.getWinnerCells()), set(tm2.getWinnerCells()))
        self.assertEqual(tm1.connections, tm2.connections)
Exemplo n.º 4
0
    def testWriteRead(self):
        tm1 = ExtendedTemporalMemory(columnDimensions=[100],
                                     cellsPerColumn=4,
                                     activationThreshold=7,
                                     initialPermanence=0.37,
                                     connectedPermanence=0.58,
                                     minThreshold=4,
                                     maxNewSynapseCount=18,
                                     permanenceIncrement=0.23,
                                     permanenceDecrement=0.08,
                                     seed=91)

        # Run some data through before serializing
        self.patternMachine = PatternMachine(100, 4)
        self.sequenceMachine = SequenceMachine(self.patternMachine)
        sequence = self.sequenceMachine.generateFromNumbers(range(5))
        for _ in range(3):
            for pattern in sequence:
                tm1.compute(pattern)

        proto1 = TemporalMemoryProto_capnp.TemporalMemoryProto.new_message()
        tm1.write(proto1)

        # Write the proto to a temp file and read it back into a new proto
        with tempfile.TemporaryFile() as f:
            proto1.write(f)
            f.seek(0)
            proto2 = TemporalMemoryProto_capnp.TemporalMemoryProto.read(f)

        # Load the deserialized proto
        tm2 = ExtendedTemporalMemory.read(proto2)

        # Check that the two temporal memory objects have the same attributes
        self.assertEqual(tm1, tm2)

        # Run a couple records through after deserializing and check results match
        tm1.compute(self.patternMachine.get(0))
        tm2.compute(self.patternMachine.get(0))
        self.assertEqual(set(tm1.getActiveCells()), set(tm2.getActiveCells()))
        self.assertEqual(set(tm1.getPredictiveCells()),
                         set(tm2.getPredictiveCells()))
        self.assertEqual(set(tm1.getWinnerCells()), set(tm2.getWinnerCells()))
        self.assertEqual(tm1.connections, tm2.connections)

        tm1.compute(self.patternMachine.get(3))
        tm2.compute(self.patternMachine.get(3))
        self.assertEqual(set(tm1.getActiveCells()), set(tm2.getActiveCells()))
        self.assertEqual(set(tm1.getPredictiveCells()),
                         set(tm2.getPredictiveCells()))
        self.assertEqual(set(tm1.getWinnerCells()), set(tm2.getWinnerCells()))
        self.assertEqual(tm1.connections, tm2.connections)
Exemplo n.º 5
0
    def testLearning(self):
        tm = ExtendedTemporalMemory(
            columnDimensions=[4],
            cellsPerColumn=10,
            learnOnOneCell=False,
            initialPermanence=0.5,
            connectedPermanence=0.6,
            activationThreshold=1,
            minThreshold=1,
            maxNewSynapseCount=2,
            permanenceDecrement=0.05,
            permanenceIncrement=0.2,
        )

        seg1 = tm.connections.createSegment(0)
        seg2 = tm.connections.createSegment(10)
        seg3 = tm.connections.createSegment(20)
        seg4 = tm.connections.createSegment(30)
        try:
            tm.connections.createSynapse(seg1, 10, 0.9)
            tm.connections.createSynapse(seg2, 20, 0.9)
            tm.connections.createSynapse(seg3, 30, 0.9)
            tm.connections.createSynapse(seg3, 41, 0.9)
            tm.connections.createSynapse(seg3, 25, 0.9)
            tm.connections.createSynapse(seg4, 0, 0.9)
        except IndexError:
            self.fail("IndexError raised unexpectedly for distal segments")

        aSeg1 = tm.apicalConnections.createSegment(0)
        aSeg2 = tm.apicalConnections.createSegment(20)
        try:
            tm.apicalConnections.createSynapse(aSeg1, 42, 0.8)
            tm.apicalConnections.createSynapse(aSeg2, 43, 0.8)
        except IndexError:
            self.fail("IndexError raised unexpectedly for apical segments")

        activeColumns = set([1, 3])
        activeExternalCells = set([1])  # will be re-indexed to 41
        activeApicalCells = set([2, 3])  # will be re-indexed to 42, 43

        tm.compute(
            activeColumns, activeExternalCells=activeExternalCells, activeApicalCells=activeApicalCells, learn=False
        )

        activeColumns = set([0, 2])
        tm.compute(activeColumns, activeExternalCells=None, activeApicalCells=None, learn=True)

        self.assertEqual(tm.activeCells, set([0, 20]))

        # distal learning
        synapse = list(tm.connections.synapsesForSegment(seg1))[0]
        self.assertEqual(tm.connections.dataForSynapse(synapse).permanence, 1.0)

        synapse = list(tm.connections.synapsesForSegment(seg2))[0]
        self.assertEqual(tm.connections.dataForSynapse(synapse).permanence, 0.9)

        synapse = list(tm.connections.synapsesForSegment(seg3))[0]
        self.assertEqual(tm.connections.dataForSynapse(synapse).permanence, 1.0)
        synapse = list(tm.connections.synapsesForSegment(seg3))[1]
        self.assertEqual(tm.connections.dataForSynapse(synapse).permanence, 1.0)
        synapse = list(tm.connections.synapsesForSegment(seg3))[2]
        self.assertEqual(tm.connections.dataForSynapse(synapse).permanence, 0.85)

        synapse = list(tm.connections.synapsesForSegment(seg4))[0]
        self.assertEqual(tm.connections.dataForSynapse(synapse).permanence, 0.9)

        # apical learning
        synapse = list(tm.apicalConnections.synapsesForSegment(aSeg1))[0]
        self.assertEqual(tm.apicalConnections.dataForSynapse(synapse).permanence, 1.0)

        synapse = list(tm.apicalConnections.synapsesForSegment(aSeg2))[0]
        self.assertEqual(tm.apicalConnections.dataForSynapse(synapse).permanence, 1.0)
Exemplo n.º 6
0
class NIK(object):
    """Class implementing NIK"""
    def __init__(
        self,
        minDx=-2.0,
        maxDx=2.0,
        minDy=-2.0,
        maxDy=2.0,
        minTheta1=0.0,
        maxTheta1=85.0,
        minTheta2=0.0,
        maxTheta2=360.0,
    ):

        self.dxEncoder = ScalarEncoder(5, minDx, maxDx, n=75, forced=True)
        self.dyEncoder = ScalarEncoder(5, minDy, maxDy, n=75, forced=True)
        self.externalSize = self.dxEncoder.getWidth()**2
        self.externalOnBits = self.dxEncoder.w**2

        self.theta1Encoder = ScalarEncoder(5,
                                           minTheta1,
                                           maxTheta1,
                                           n=75,
                                           forced=True)
        self.theta2Encoder = ScalarEncoder(5,
                                           minTheta2,
                                           maxTheta2,
                                           n=75,
                                           forced=True)
        self.bottomUpInputSize = self.theta1Encoder.getWidth(
        ) * self.theta2Encoder.getWidth()
        self.bottomUpOnBits = self.theta1Encoder.w * self.theta2Encoder.w

        self.minDx = 100.0
        self.maxDx = -100.0
        self.minTheta1 = minTheta1
        self.minTheta2 = minTheta2
        self.maxTheta1 = maxTheta1
        self.maxTheta2 = maxTheta2

        self.trainingIterations = 0
        self.testIterations = 0
        self.maxPredictionError = 0
        self.totalPredictionError = 0
        self.numMissedPredictions = 0

        self.tm = TM(columnDimensions=(self.bottomUpInputSize, ),
                     basalInputDimensions=(self.externalSize, ),
                     cellsPerColumn=1,
                     initialPermanence=0.4,
                     connectedPermanence=0.5,
                     minThreshold=self.externalOnBits,
                     maxNewSynapseCount=40,
                     permanenceIncrement=0.1,
                     permanenceDecrement=0.00,
                     activationThreshold=int(
                         0.75 * (self.externalOnBits + self.bottomUpOnBits)),
                     predictedSegmentDecrement=0.00,
                     checkInputs=False)

        print >> sys.stderr, "TM parameters:"
        print >> sys.stderr, "  num columns=", self.tm.getColumnDimensions()
        print >> sys.stderr, "  activation threshold=", self.tm.getActivationThreshold(
        )
        print >> sys.stderr, "  min threshold=", self.tm.getMinThreshold()
        print >> sys.stderr, "  basal input dimensions=", self.tm.getBasalInputDimensions(
        )
        print >> sys.stderr
        print >> sys.stderr

    def compute(self, xt1, yt1, xt, yt, theta1t1, theta2t1, theta1, theta2,
                learn):
        """
    The main function to call.
    If learn is False, it will print a prediction: (theta1, theta2)
    """
        dx = xt - xt1
        dy = yt - yt1

        self.minDx = min(self.minDx, dx)
        self.maxDx = max(self.maxDx, dx)

        print >> sys.stderr, "Learn: ", learn
        print >> sys.stderr, "Training iterations: ", self.trainingIterations
        print >> sys.stderr, "Test iterations: ", self.testIterations
        print >> sys.stderr, "Xt's: ", xt1, yt1, xt, yt, "Delta's: ", dx, dy
        print >> sys.stderr, "Theta t-1: ", theta1t1, theta2t1, "t:", theta1, theta2

        bottomUpSDR = self.encodeThetas(theta1, theta2)
        self.decodeThetas(bottomUpSDR)

        # Encode the inputs appropriately and train the HTM
        externalSDR = self.encodeDeltas(dx, dy)

        if learn:
            # During learning we provide the current pose angle as bottom up input
            bottomUpSDR = self.encodeThetas(theta1, theta2)
            self.trainTM(bottomUpSDR, externalSDR)
            self.trainingIterations += 1
        else:
            # During inference we provide the previous pose angle as bottom up input
            # If we don't get a prediction, we keep trying random shifts until we get
            # something.
            predictedCells = []
            newt1 = theta1t1
            newt2 = theta2t1
            newdx = dx
            newdy = dy
            angleRange = 10
            numAttempts = 1
            while len(predictedCells) == 0 and numAttempts < 3:
                print >> sys.stderr, "Attempt:", numAttempts,
                print >> sys.stderr, "Trying to predict using thetas:", newt1, newt2,
                print >> sys.stderr, "and deltas:", newdx, newdy

                externalSDR = self.encodeDeltas(newdx, newdy)
                bottomUpSDR = self.encodeThetas(newt1, newt2)
                predictedCells = self.inferTM(bottomUpSDR, externalSDR)
                predictedValues = self.decodeThetas(predictedCells)

                print >> sys.stderr, "Predicted values", predictedValues

                newt1 = theta1t1 + random.randrange(-angleRange, angleRange)
                newt2 = theta2t1 + random.randrange(-angleRange, angleRange)
                newdx = dx + (random.random() / 2.0 - 0.25)
                newdy = dy + (random.random() / 2.0 - 0.25)

                # Ensure we are in bounds otherwise we get an exception
                newt1 = min(self.maxTheta1, max(self.minTheta1, newt1))
                newt2 = min(self.maxTheta2, max(self.minTheta2, newt2))
                newdx = min(2.0, max(-2.0, newdx))
                newdy = min(2.0, max(-2.0, newdy))

                numAttempts += 1
                if numAttempts % 10 == 0: angleRange += 2

            print predictedValues
            # Accumulate errors for our metrics
            if len(predictedCells) == 0:
                self.numMissedPredictions += 1
            self.testIterations += 1
            error = abs(predictedValues[0] - theta1) + abs(predictedValues[1] -
                                                           theta2)
            self.totalPredictionError += error
            if self.maxPredictionError < error:
                self.maxPredictionError = error
                print >> sys.stderr, "Error: ", error

        print >> sys.stderr

    def reset(self):
        self.tm.reset()

    def encodeDeltas(self, dx, dy):
        """Return the SDR for dx,dy"""
        dxe = self.dxEncoder.encode(dx)
        dye = self.dyEncoder.encode(dy)
        ex = numpy.outer(dxe, dye)
        return ex.flatten().nonzero()[0]

    def encodeThetas(self, theta1, theta2):
        """Return the SDR for theta1 and theta2"""
        # print >> sys.stderr, "encoded theta1 value = ", theta1
        # print >> sys.stderr, "encoded theta2 value = ", theta2
        t1e = self.theta1Encoder.encode(theta1)
        t2e = self.theta2Encoder.encode(theta2)
        # print >> sys.stderr, "encoded theta1 = ", t1e.nonzero()[0]
        # print >> sys.stderr, "encoded theta2 = ", t2e.nonzero()[0]
        ex = numpy.outer(t2e, t1e)
        return ex.flatten().nonzero()[0]

    def decodeThetas(self, predictedCells):
        """
    Given the set of predicted cells, return the predicted theta1 and theta2
    """
        a = numpy.zeros(self.bottomUpInputSize)
        a[predictedCells] = 1
        a = a.reshape(
            (self.theta1Encoder.getWidth(), self.theta1Encoder.getWidth()))
        theta1PredictedBits = a.mean(axis=0).nonzero()[0]
        theta2PredictedBits = a.mean(axis=1).nonzero()[0]

        # To decode it we need to create a flattened array again and pass it
        # to encoder.
        # TODO: We use encoder's topDownCompute method - not sure if that is best.
        t1 = numpy.zeros(self.theta1Encoder.getWidth())
        t1[theta1PredictedBits] = 1
        t1Prediction = self.theta1Encoder.topDownCompute(t1)[0].value

        t2 = numpy.zeros(self.theta2Encoder.getWidth())
        t2[theta2PredictedBits] = 1
        t2Prediction = self.theta2Encoder.topDownCompute(t2)[0].value

        # print >> sys.stderr, "predicted cells = ", predictedCells
        # print >> sys.stderr, "decoded theta1 bits = ", theta1PredictedBits
        # print >> sys.stderr, "decoded theta2 bits = ", theta2PredictedBits
        # print >> sys.stderr, "decoded theta1 value = ", t1Prediction
        # print >> sys.stderr, "decoded theta2 value = ", t2Prediction

        return t1Prediction, t2Prediction

    def printStats(self):
        print >> sys.stderr, "min/max dx=", self.minDx, self.maxDx
        print >> sys.stderr, "Total number of segments=", numSegments(self.tm)
        if self.testIterations > 0:
            print >> sys.stderr, "Maximum prediction error: ", self.maxPredictionError
            print >> sys.stderr, "Mean prediction error: ", self.totalPredictionError / self.testIterations
            print >> sys.stderr, "Num missed predictions: ", self.numMissedPredictions

    def trainTM(self, bottomUp, externalInput):
        # print >> sys.stderr, "Bottom up: ", bottomUp
        # print >> sys.stderr, "ExternalInput: ",externalInput
        self.tm.depolarizeCells(externalInput, learn=True)
        self.tm.activateCells(bottomUp,
                              reinforceCandidatesExternalBasal=externalInput,
                              growthCandidatesExternalBasal=externalInput,
                              learn=True)
        # print >> sys.stderr, ("new active cells " + str(self.tm.getActiveCells()))
        print >> sys.stderr, "Total number of segments=", numSegments(self.tm)

    def inferTM(self, bottomUp, externalInput):
        """
    Run inference and return the set of predicted cells
    """
        self.reset()
        # print >> sys.stderr, "Bottom up: ", bottomUp
        # print >> sys.stderr, "ExternalInput: ",externalInput
        self.tm.compute(bottomUp,
                        activeCellsExternalBasal=externalInput,
                        learn=False)
        # print >> sys.stderr, ("new active cells " + str(self.tm.getActiveCells()))
        # print >> sys.stderr, ("new predictive cells " + str(self.tm.getPredictiveCells()))
        return self.tm.getPredictiveCells()

    def save(self, filename="temp.pkl"):
        """
    Save TM in the filename specified above
    """
        output = open(filename, 'wb')
        cPickle.dump(self.tm, output, protocol=cPickle.HIGHEST_PROTOCOL)

    def load(self, filename="temp.pkl"):
        """
    Save TM in the filename specified above
    """
        inputFile = open(filename, 'rb')
        self.tm = cPickle.load(inputFile)
Exemplo n.º 7
0
    def testLearning(self):
        tm = ExtendedTemporalMemory(columnDimensions=[4],
                                    cellsPerColumn=10,
                                    learnOnOneCell=False,
                                    initialPermanence=0.5,
                                    connectedPermanence=0.6,
                                    activationThreshold=1,
                                    minThreshold=1,
                                    maxNewSynapseCount=2,
                                    permanenceDecrement=0.05,
                                    permanenceIncrement=0.2)

        seg1 = tm.connections.createSegment(0)
        seg2 = tm.connections.createSegment(10)
        seg3 = tm.connections.createSegment(20)
        seg4 = tm.connections.createSegment(30)
        try:
            tm.connections.createSynapse(seg1, 10, 0.9)
            tm.connections.createSynapse(seg2, 20, 0.9)
            tm.connections.createSynapse(seg3, 30, 0.9)
            tm.connections.createSynapse(seg3, 41, 0.9)
            tm.connections.createSynapse(seg3, 25, 0.9)
            tm.connections.createSynapse(seg4, 0, 0.9)
        except IndexError:
            self.fail("IndexError raised unexpectedly for distal segments")

        aSeg1 = tm.apicalConnections.createSegment(0)
        aSeg2 = tm.apicalConnections.createSegment(20)
        try:
            tm.apicalConnections.createSynapse(aSeg1, 42, 0.8)
            tm.apicalConnections.createSynapse(aSeg2, 43, 0.8)
        except IndexError:
            self.fail("IndexError raised unexpectedly for apical segments")

        activeColumns = set([1, 3])
        activeExternalCells = set([1])  # will be re-indexed to 41
        activeApicalCells = set([2, 3])  # will be re-indexed to 42, 43

        tm.compute(activeColumns,
                   activeExternalCells=activeExternalCells,
                   activeApicalCells=activeApicalCells,
                   learn=False)

        activeColumns = set([0, 2])
        tm.compute(activeColumns,
                   activeExternalCells=None,
                   activeApicalCells=None,
                   learn=True)

        self.assertEqual(tm.activeCells, set([0, 20]))

        # distal learning
        synapse = list(tm.connections.synapsesForSegment(seg1))[0]
        self.assertEqual(
            tm.connections.dataForSynapse(synapse).permanence, 1.0)

        synapse = list(tm.connections.synapsesForSegment(seg2))[0]
        self.assertEqual(
            tm.connections.dataForSynapse(synapse).permanence, 0.9)

        synapse = list(tm.connections.synapsesForSegment(seg3))[0]
        self.assertEqual(
            tm.connections.dataForSynapse(synapse).permanence, 1.0)
        synapse = list(tm.connections.synapsesForSegment(seg3))[1]
        self.assertEqual(
            tm.connections.dataForSynapse(synapse).permanence, 1.0)
        synapse = list(tm.connections.synapsesForSegment(seg3))[2]
        self.assertEqual(
            tm.connections.dataForSynapse(synapse).permanence, 0.85)

        synapse = list(tm.connections.synapsesForSegment(seg4))[0]
        self.assertEqual(
            tm.connections.dataForSynapse(synapse).permanence, 0.9)

        # apical learning
        synapse = list(tm.apicalConnections.synapsesForSegment(aSeg1))[0]
        self.assertEqual(
            tm.apicalConnections.dataForSynapse(synapse).permanence, 1.0)

        synapse = list(tm.apicalConnections.synapsesForSegment(aSeg2))[0]
        self.assertEqual(
            tm.apicalConnections.dataForSynapse(synapse).permanence, 1.0)