All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bnd.math.business.sym.onedim.SymmetricConfigurationEnumerator Maven / Gradle / Ivy

The newest version!
package com.bnd.math.business.sym.onedim;

import com.bnd.function.enumerator.ListEnumerator;
import com.bnd.function.enumerator.ListEnumeratorFactory;
import org.apache.commons.math3.util.ArithmeticUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class SymmetricConfigurationEnumerator {

	protected final int arraySize;
	protected final int alphabetSize;
	protected final ListEnumeratorFactory enumerator;

	public SymmetricConfigurationEnumerator(
		int arraySize,
		int alphabetSize,
		ListEnumeratorFactory enumerator
	) {
		this.arraySize = arraySize;
		this.alphabetSize = alphabetSize;
		this.enumerator = enumerator;
	}

	private static boolean isDivisibleBy(int num, Collection divisors) {
		for (Integer divisor : divisors) {
			if (num % divisor == 0) {
				return true;
			}
		}
		return false;
	}

	public static List calcPrimeDivisors(int num) {
		List primeDivisors = new ArrayList();
		for (int divisor = 2; divisor <= num; divisor++) {
			if (num % divisor == 0 && !isDivisibleBy(divisor, primeDivisors)) {
				primeDivisors.add(divisor);
			}			
		}
		return primeDivisors;
	}

	public static List calcPrimeDivisorPows(int num) {
		List primePows = new ArrayList();
		List primeDivisors = calcPrimeDivisors(num);
		for (int primeDivisor : primeDivisors) {
			int primePow = primeDivisor;
			while (num % primePow == 0) {
				primePows.add(primePow);
				primePow *= primeDivisor;
			}
		}
		return primePows;
	}

	public long enumerateAll() {
		return enumerateAll(alphabetSize);
	}

	protected long enumerateAll(int alphabetSize) {
		final List primeDivisors = calcPrimeDivisors(arraySize);
		final ListEnumerator primeCombEnumerator = enumerator.createInstance(false, primeDivisors);
		final int omega = primeDivisors.size();

		long sum = 0;
		for (int i = 1; i <= omega; i++) {
			long partialSum = 0;
			for (List selectedPrimes : primeCombEnumerator.enumerate(i)) {
//				System.out.println(selectedPrimes);
				int primeProduct = 1;
				for (Integer selectedPrime : selectedPrimes) primeProduct *=  selectedPrime;
				partialSum += Math.pow(alphabetSize, arraySize / primeProduct); 
			}
			if (i % 2 == 0)
				sum -= partialSum;
			else
				sum += partialSum;				
		}
		return sum;
	}

	public long enumerate(int activeCellsNum) {
		if (activeCellsNum == 0) { 
			return enumerateAll(alphabetSize - 1);
		}
		final List arrayPrimeDivisors = calcPrimeDivisors(arraySize);
		final List activeCellsPrimeDivisors = calcPrimeDivisors(activeCellsNum);
		activeCellsPrimeDivisors.retainAll(arrayPrimeDivisors);

		if (activeCellsPrimeDivisors.isEmpty())
			return 0;

//		System.out.println(activeCellsPrimeDivisors);

		final ListEnumerator primeCombEnumerator = enumerator.createInstance(false, activeCellsPrimeDivisors);
		final int omega = activeCellsPrimeDivisors.size();

		long sum = 0;
		for (int i = 1; i <= omega; i++) {
			long partialSum = 0;
			for (List selectedPrimes : primeCombEnumerator.enumerate(i)) {
//				System.out.println(selectedPrimes);
				int primeProduct = 1;
				for (Integer selectedPrime : selectedPrimes) primeProduct *=  selectedPrime;
				partialSum += ArithmeticUtils.binomialCoefficientDouble(arraySize /  primeProduct, activeCellsNum / primeProduct)
								* Math.pow((alphabetSize - 1), (arraySize - activeCellsNum) / primeProduct);
			}
			if (i % 2 == 0)
				sum -= partialSum;
			else
				sum += partialSum;				
		}
		return sum;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy