Package cc.redberry.core.tensor.random

Source Code of cc.redberry.core.tensor.random.RandomProduct

/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2012:
*   Stanislav Poslavsky   <stvlpos@mail.ru>
*   Bolotin Dmitriy       <bolotin.dmitriy@gmail.com>
*
* This file is part of Redberry.
*
* Redberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Redberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Redberry. If not, see <http://www.gnu.org/licenses/>.
*/
package cc.redberry.core.tensor.random;

import cc.redberry.core.indices.IndicesUtils;
import cc.redberry.core.indices.IndexType;
import cc.redberry.core.indices.IndicesFactory;
import cc.redberry.core.indices.IndicesTypeStructure;
import cc.redberry.core.indices.SimpleIndices;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math.random.BitsStreamGenerator;
import org.apache.commons.math.random.Well44497b;
import cc.redberry.core.context.CC;
import cc.redberry.core.context.NameDescriptor;
import cc.redberry.core.tensor.Product;
import cc.redberry.core.tensor.SimpleTensor;
import cc.redberry.core.combinatorics.Symmetry;

public final class RandomProduct {
    private static final int ALPHABET_SIZE = 26;
    private final static byte[] TYPES = {0, 1, 2, 3};
    private final BitsStreamGenerator random;
    private final int nMax, nMin;
    private final boolean withSymmetries;
    private long seed;
    private final int[] maxIndicesPerTensor;
    private final int[] indicesCount;
    private final int[] maxMinFreeIndicesCount;
    private final int maxTensorCount;
    private final int maxScalarsCount;

    public RandomProduct(int nMax, int nMin,
            int[] maxMinFreeIndicesCount, int[] indicesCount,
            int[] maxIndicesPerTensor,
            int maxTensorCount, int maxScalarsCount, boolean withSymmetries) {
        this.nMax = nMax;
        this.nMin = nMin;
        this.withSymmetries = withSymmetries;
        this.maxMinFreeIndicesCount = maxMinFreeIndicesCount;
        this.indicesCount = indicesCount;
        this.maxIndicesPerTensor = maxIndicesPerTensor;
        this.maxTensorCount = maxTensorCount;
        this.maxScalarsCount = maxScalarsCount;
        random = new Well44497b();
        reset();
    }

    public void reset() {
        random.setSeed(seed = random.nextLong());
    }

    public void reset(long seed) {
        random.setSeed(this.seed = seed);
    }

    public long getSeed() {
        return seed;
    }

    public Product next() {
        int i, j;

        int[] minFree = new int[IndexType.TYPES_COUNT];
        for (i = 0; i < IndexType.TYPES_COUNT; ++i)
            minFree[i] = nextInt(random, maxMinFreeIndicesCount[i]);

        int N = nMin + nextInt(random, nMax - nMin);
        List<NameDescriptor> descriptors = new ArrayList<>();
        int[] typesCount;
        NameDescriptor nameDescriptor;
        for (i = 0; i < N; ++i) {
            typesCount = new int[IndexType.TYPES_COUNT];
            for (j = 0; j < IndexType.TYPES_COUNT; ++j)
                typesCount[j] = nextInt(random, maxIndicesPerTensor[j]);
            IndicesTypeStructure typeStructure = new IndicesTypeStructure(TYPES, typesCount);
            descriptors.add(nameDescriptor = new NameDescriptor(getName(i), typeStructure));
            CC.getNameManager().mapNameDescriptor(descriptors.get(i));
            if (withSymmetries)
                addRandomSymmetries(nameDescriptor);
        }

        Product product = new Product();
        IndicesProvider indicesProvider = new IndicesProvider(random, indicesCount, minFree);
        SimpleIndices ind;
        int scalars = 0;
        while (!descriptors.isEmpty() && product.size() <= maxTensorCount) {
            int descriptorIndex = nextInt(random, descriptors.size());
            NameDescriptor nd = descriptors.get(descriptorIndex);
            if (nd.getIndexTypeStructure().size() == 0)
                if (scalars++ > maxScalarsCount) {
                    descriptors.remove(descriptorIndex);
                    continue;
                }
            ind = indicesProvider.next(nd);
            if (ind == null) {
                descriptors.remove(descriptorIndex);
                continue;
            }
            product.add(new SimpleTensor(nd.getId(), ind));
        }
        return product;
    }

    public static String getName(int i) {
        int second = i / ALPHABET_SIZE;
        int first = i - second * ALPHABET_SIZE;
        if (second == 0)
            return new String(new char[]{(char) (0x41 + first)});
        else
            return new String(new char[]{(char) (0x40 + second), (char) (0x41 + first)});
    }

    public static int nextInt(BitsStreamGenerator generator, int n) {
        if (n == 0)
            return 0;
        return generator.nextInt(n);
    }

    private static class IndicesProvider {
        final static byte[] TYPES = {0, 1, 2, 3};
        final BitsStreamGenerator random;
        final int[][] indices;
        final int[] lengths;
        final int[] minLegth;

        IndicesProvider(BitsStreamGenerator random, int[] indicesCounts, int[] minLegth) {
            this.minLegth = minLegth;
            indices = new int[IndexType.TYPES_COUNT][];
            int i, j;
            for (i = 0; i < TYPES.length; ++i) {
                indices[i] = new int[indicesCounts[i] * 2];
                for (j = 0; j < indicesCounts[i]; ++j) {
                    indices[i][j] = IndicesUtils.createIndex(j, (byte) i, false);
                    indices[i][indicesCounts[i] + j] = IndicesUtils.createIndex(j, (byte) i, true);
                }
            }
            lengths = indicesCounts.clone();
            for (i = 0; i < TYPES.length; ++i)
                lengths[i] *= 2;

            this.random = random;
        }

        private int next(byte type) {
            if (lengths[type] == 0)
                throw new IllegalStateException();
            int n = nextInt(random, lengths[type]);
            int index = indices[type][n];
            if (n != lengths[type] - 1)
                System.arraycopy(indices[type], n + 1, indices[type], n, lengths[type] - n - 1);
            --lengths[type];
            return index;
        }

        SimpleIndices next(NameDescriptor nd) {
            IndicesTypeStructure typeStructure = nd.getIndexTypeStructure();
            final int[] indices = new int[typeStructure.size()];
            for (int i = 0; i < indices.length; ++i) {
                if (lengths[typeStructure.get(i)] <= minLegth[typeStructure.get(i)])
                    return null;
                indices[i] = next(typeStructure.get(i));
            }
            return IndicesFactory.createSimple(indices);
        }
    }

    private void addRandomSymmetries(NameDescriptor descriptor) {
        if (!descriptor.getSymmetries().isEmpty())
            throw new RuntimeException("Symmetries already exists");
        IndicesTypeStructure typeStructure = descriptor.getIndexTypeStructure();
        int i;
        for (byte type = 0; type < IndexType.TYPES_COUNT; ++type) {
            IndicesTypeStructure.TypeData typeData = typeStructure.getTypeDatas(type);
            if (typeData == null)
                continue;
            if (typeData.length == 0)//redundant
                continue;
            for (i = 0; i < random.nextInt(3); ++i)
                descriptor.addSymmetry(type, new Symmetry(getRandomPermutation(typeData.length, random), false));
//                try {
//                    descriptor.addSymmetry(type, new Symmetry(getRandomPermutation(typeData.length, random), random.nextBoolean()));
//                } catch (InconsistentGeneratorsException exception) {
//                }
        }
    }

    public static int[] getRandomPermutation(final int dimension, BitsStreamGenerator generator) {
        if (dimension == 0)
            return new int[0];
        int[] permutation = new int[dimension];
        if (dimension == 1)
            return permutation;
        int i, r = generator.nextInt(1000);
        //cycle permutation
        if (r < 100) {
            for (i = 0; i < dimension - 1; ++i)
                permutation[i] = i + 1;
            permutation[dimension - 1] = 0;
            return permutation;
        }
        for (i = 1; i < dimension; ++i)
            permutation[i] = i;
        //else composition of transpositions
        if (r < 700) {
            int p1, p2;
            final int tries = generator.nextInt(3) + 1;
            for (i = 0; i < tries; ++i) {
                while ((p1 = generator.nextInt(dimension)) == (p2 = generator.nextInt(dimension)));
                swap(permutation, p1, p2);
            }
        }
        //else identity
        return permutation;
    }

    private static void swap(int[] a, int p1, int p2) {
        int c = a[p1];
        a[p1] = a[p2];
        a[p2] = c;
    }
}
TOP

Related Classes of cc.redberry.core.tensor.random.RandomProduct

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.