Example #1
0
def changeofbasis(dimension, degree):
    liebasis = ts.logsigkeys(dimension, degree)
    tensorbasis = ts.sigkeys(dimension, degree)
    n = ts.logsigdim(dimension, degree)
    m = ts.sigdim(dimension, degree)
    matrix = np.zeros((n, m))
    pos = tensorbasis.split()
    columnindex = []
    pos[0] = '(0)'
    for row in pos:
        row = row.strip('(')
        row = row.strip(')')
        row = row.split(',')

        row = [int(i) for i in row]
        columnindex.append(row)
    #print(columnindex)

    rowindex = liebasis.split()
    expand = []
    for i in range(n):
        B = Lietotensor(rowindex[i])
        #print(B)
        for j in B:
            for k in range(m):
                #print(type(j[1]))
                #print(type(k))
                if j[1] == columnindex[k]:
                    matrix[i][k] = matrix[i][k] + j[0]
    return matrix
def get_words(dim, order):
    keys = [
        tuple([t]) if isinstance(t, int) else t
        for t in map(eval,
                     tosig.sigkeys(dim, order).split())
    ]
    keys = [tuple(np.array(t) - 1) for t in keys]
    return keys
def get_keys(dim, order):
    s = tosig.sigkeys(dim, order)

    tuples = []

    for t in s.split():
        if len(t) > 2:
            t = t.replace(")", ",)")

        tuples.append(ast.literal_eval(t))

    return tuples
Example #4
0
def plot_sig(order,
             train_sig,
             test_sig,
             generated_sig1,
             different_sig=None,
             plot_all=False,
             labels=None):
    if labels is None:
        labels = [
            "Different data",
            "Train data",
            "Test data",
            "VAE normal",
        ]

    keys = sigkeys(2, order).split()
    factor = []
    for i in keys:
        factor.append((np.ceil((len(i) - 2) / 2)))
    factor = np.array(factor)

    #     PROJECTIONS = [(4, 5), (3, 4), (7, 8), (9, 10)]
    PROJECTIONS = [(4, 5), (2, 4), (6, 7), (9, 2)]
    f, p = plt.subplots(1, 4, figsize=(20, 3))
    for k, projection in enumerate(PROJECTIONS):

        if different_sig is not None:
            p[k].scatter(different_sig[:, projection[0]], different_sig[:, projection[1]],\
                       label=labels[0], alpha = 0.7, color = 'tab:red')

        if different_sig is None or plot_all is True:
            p[k].scatter(train_sig[:, projection[0]], train_sig[:, projection[1]],\
                       label=labels[1], alpha = 0.7, color = 'tab:blue')

        p[k].scatter(test_sig[:, projection[0]], test_sig[:, projection[1]],\
                       label=labels[2], alpha = 0.7, color = 'tab:green')
        p[k].scatter(generated_sig1[:, projection[0]], generated_sig1[:, projection[1]],\
                         label=labels[3], alpha = 0.7, color = 'tab:orange')

        p[k].set_xlabel(keys[projection[0]], fontsize=10)
        p[k].set_ylabel(keys[projection[1]], fontsize=10)
        p[k].legend()
        p[k].grid()
    plt.suptitle('Signature')
    plt.show()
Example #5
0
def get_sig_keys(dico,sig_level):
    
    ndims = len(dico)
    
    keys = esig.sigkeys(ndims,sig_level).split("(")
    sig_keys = []

    for i in range(2,len(keys)-1):
        sig_keys.append(np.array(keys[i][:-2].split(',')))
    sig_keys.append(np.array(keys[len(keys)-1][:-1].split(',')))
    
    features_names = {}
    for i in range(len(sig_keys)):
        separator = '-'
        name = separator.join([dico[int(e)] for e in sig_keys[i]])
        features_names[1+i]= name

    return features_names
Example #6
0
def linsig(position_vector, degree, start=None, end=None):
    """
    Function computes the truncated signature up to degree 'degree' of a single linear path from 0 to a position vector specified.

    Args:
        position_vector (list): a list of coordinates
        degree (int): the highest degree of a signature term to return
        start (float): optional, can input the intial time value, default 0
        stop (float): optional can input the final time value, default 1

    Returns:
        signature (np.array): vector of signature values


    """
    if start == None:
        start = 0
    if end == None:
        end = 1
    dimension = len(position_vector)
    keys = ts.sigkeys(dimension, degree)
    pos = keys.split()
    pos_out = []
    pos[0] = '(0)'
    for row in pos:
        row = row.strip('(')
        row = row.strip(')')
        row = row.split(',')

        row = [int(i) for i in row]
        pos_out.append(row)
    pos_out.pop(0)
    signature = [1]
    for i in pos_out:
        sigj = 1
        l = len(i)
        for j in i:
            sigj = sigj * position_vector[j - 1]
        sigj = sigj * (end - start)**l
        sigj = sigj / math.factorial(l)
        signature.append(sigj)

    signature = np.array(signature)
    return signature
Example #7
0
 def sig_keys(self, dimension, depth):
     return tosig.sigkeys(dimension, depth)
Example #8
0
def shuffle_test(l, a, dims, degs):
    """ Evaluates whether a product sum of shuffles is equal to the multiplication evaluated pairs of signature elements

    stream2sig and stream2logsig functions included in the esig library return a list of values according to (a) the dimensions present in the data and (b) signature degrees.
    sigkeys and logsigkeys functions included in the esig library return keys which correspond to each of the signature element produced with either stream2sig and stream2logsig functions.

    Properties of path signature are such that for any 2 keys, if one multiplies the values which they correspond to, the result of the multiplication is equal to a sum of
    values for all keys which are shuffles of the two keys. This function evaluates whether this property of path signature holds true for all possible pairs of
    signature elements whose keys, together, are shorter or as long as the longest keys of values included in the signature.

    Args:
        l (int): length of a random path to be produced
        a (list): list of modifiers applied at each step of the random path
        dims (int): number of dimensions each path step has
        degs (int): number of signature degrees to be used in the test

    Returns:
        str: "ok" if the test has been successful

    Raises:
        ValueError: If the sum of values corresponding to key shuffles is not equal to the multiplication of the pair of values with corresponding keys

    Example:
        >>> shuffle_test(100,[-1,0,1],3,3)
        "ok"

    """

    test_path = np.array(
        ax.random_path(l, a, dims)
    )  # generates a random path given number of path steps 'l', possible moves at each step 'a',
    # and the number dimensions at each path step 'dims'
    signature = list(
        ts.stream2sig(test_path, degs)
    )  # generates signature for the provided random path and chosen number of signature degrees 'degs'

    #5 LINES BELOW COULD BE A SEPARATE TEST
    if signature[0] != 1:  # check if the first signature element is 1
        print(
            "The first signature element has a value different from 0 in shuffle_test"
        )
        raise ValueError
    else:
        pass

    keys = ts.sigkeys(dims, degs).split(
    )  # generates keys of the signature for the provided random path
    keys2 = []
    lengths = []
    for row in keys:
        row = row.strip('(')
        row = row.strip(')')
        if len(row) > 0:
            row = row.split(',')
            lengths.append(len(row))
            keys2.append(row)
        else:
            pass

    del signature[0]

    keys3 = list(zip(keys2, lengths, signature))

    max_mutant_length = len(keys2[-1])

    # obtain all possible mutations which are no longer than the max_mutant_length
    mutants = []
    mutant_parent_indices = []
    for row_ind, row in enumerate(keys3):
        vals = []
        inds = []
        for col_ind, col in enumerate(keys3):
            if row_ind != col_ind:
                tmp = list(row[0]) + list(col[0])
                if len(tmp) <= max_mutant_length:
                    val = [list(row[0]), list(col[0])]
                    vals.append(val)
                    ind = [row_ind, col_ind]
                    inds.append(ind)
        mutants.extend(vals)
        mutant_parent_indices.extend(inds)

    # generate shuffles, get results
    shuffle_prep = list(zip(mutants, mutant_parent_indices))
    for row in shuffle_prep:
        my_shuffles = ax.shuffles(row[0][0], row[0][1])

        # sum shuffles, knowing their values in keys3 table
        shuffle_product = 0
        for shuffle in my_shuffles:
            for x in keys3:
                if str(x[0]) != str(shuffle):
                    pass
                else:
                    shuffle_product = shuffle_product + x[2]

        # multiply components, knowing their indics in keys3 table
        parent1 = row[1][0]
        parent1 = keys3[parent1][2]
        parent2 = row[1][1]
        parent2 = keys3[parent2][2]
        mutant_parent_multiplication = parent1 * parent2

        # shuffle product - multiplication product into 'solutions' variable
        solution = shuffle_product - mutant_parent_multiplication
        if solution >= -0.00001 and solution <= 0.00001:
            pass
        else:
            raise ValueError
    return 1
Example #9
0
def compare_reverse_test(l, a, dims, degs):
    """ Compare signature of a random path with its inverse

    If a path has steps [a,b,c], its inverse has steps [c,b,a]

    Args:
        l (int): length of the random path to be produced
        a (list): list of modifiers applied at each step of the random path
        dims (int): number of dimensions each path step has
        degs (int): number of signature degrees to be used in the test

    Returns:
        str: "ok" if the test has been successful

    Raises:
        ValueError: If the signature of the inverse path is not actually computed for the inverse of the original path

    Example:
        >>> compare_reverse_test(100,[-1,0,1],2,4)
        "ok"
    """

    input = np.array(ax.random_path(l, a, dims))

    # make a reverse path
    rev = list(reversed(input))
    rev = [list(x) for x in rev]
    rev = np.array(rev)
    out_sig = ts.stream2sig(input, degs)
    out_rev = ts.stream2sig(rev, degs)

    # calculate corresponding 'k' addresses for the signature elements of the original and the inverse paths
    pos = ts.sigkeys(dims, degs).split()
    how_long = []
    pos_out = []
    pos_rev = []
    for row in pos:
        row = row.strip('(')
        row = row.strip(')')
        row = row.split(',')
        pos_out.append(''.join(row))
        pos_rev.append(''.join(list(reversed(row))))
        if len(row) % 2 == 0:  # even key lengths
            how_long.append(-1)
        else:  # odd key lengths
            how_long.append(1)

    # match addresses for the signature elements of the original and the inverse paths
    out_and_rev = []
    for ind, row in enumerate(pos_out):
        temp = []
        temp.append(out_sig[ind])
        temp.append(out_rev[pos_rev.index(row)])
        temp.append(how_long[ind])
        out_and_rev.append(temp)

    # check if the differences are correct (corresponding addresses of odd length have opposite signs, corresponding addresses with even length have the sae signs)
    out = []
    for row in out_and_rev:
        test_calculation = row[-1] * row[-3] + row[-2]
        out.append(test_calculation)

    if out[0] != 2:
        raise ValueError
    for row in out[1:]:
        if row >= -0.00001 and row <= 0.00001:
            pass
        else:
            raise ValueError
    return 1