package polyofdm.cc.powercontrol;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import polyofdm.matrixgen.Utils;
import Jama.Matrix;
public class PowerControlledCC {
private final Matrix degreeToCCarrierMatrix;
private final Matrix usedToDegreeMatrix;
private final int[] usedCarriers;
private final int[] cCarriers;
public PowerControlledCC(int allCarriers, Set<Integer> cancellationCarriers) {
validateDefinition(allCarriers, cancellationCarriers);
this.usedCarriers = getUsedCarriers(allCarriers, cancellationCarriers);
this.cCarriers = getCancellationCarriers(allCarriers, cancellationCarriers);
this.degreeToCCarrierMatrix = createMatrix(allCarriers);
System.out.println("this.degreeToCCarrierMatrix");
this.degreeToCCarrierMatrix.print(15, 5);
Matrix usedToCCDirectMatrix = polyofdm.cc.full.FullCC.createCancellationMatrix(allCarriers, cancellationCarriers);
this.usedToDegreeMatrix = this.degreeToCCarrierMatrix.transpose().times(usedToCCDirectMatrix);
}
private Matrix createMatrix(int allCarriers) {
double[] ccWeightings = createWeightings(cCarriers);
Matrix cCarriersToCancelledDegrees = new Matrix(cCarriers.length, cCarriers.length);
for (int degree = 0; degree < cCarriers.length; degree++) {
for (int cCarrierIndex = 0; cCarrierIndex < cCarriers.length; cCarrierIndex++) {
cCarriersToCancelledDegrees.set(degree, cCarrierIndex, power(cCarriers[cCarrierIndex] - ((usedCarriers.length+cCarriers.length-1)/2d), degree) * ccWeightings[cCarrierIndex]);
}
}
Utils.makeOrthoGramSchmidt(cCarriersToCancelledDegrees);
System.out.println("cCarriersToCancelledDegrees0");
cCarriersToCancelledDegrees.print(15, 15);
cCarriersToCancelledDegrees = resort(cCarriersToCancelledDegrees);
System.out.println("cCarriersToCancelledDegrees resorted");
cCarriersToCancelledDegrees.print(15, 15);
System.out.println("cCarriersToCancelledDegrees gram schmidt");
cCarriersToCancelledDegrees.print(15, 15);
return cCarriersToCancelledDegrees.transpose();
}
private static double[] createWeightings(int[] cCarriers)
{
double[] weightings = new double[cCarriers.length];
for (int cCarrierIndex=0; cCarrierIndex<cCarriers.length; cCarrierIndex++)
{
/*
* denominator(x)=(x_i-x_0)*....*(x_i-x_i-1)*(x_i-x_i+1)*....*(x_i-x_all-missed)
*/
double denominator = calcProduct(cCarriers,cCarrierIndex);
if (cCarriers[cCarrierIndex]%2==1)
weightings[cCarrierIndex] = -1/denominator; // Additional sign from sinus
else
weightings[cCarrierIndex] = 1/denominator;
}
return weightings;
}
private static double calcProduct(int[] cCarriers, int cCarrierIndexOut) {
double product = 1;
for (int index = 0; index < cCarriers.length; index++)
{
if (index == cCarrierIndexOut)
continue;
product = product * (cCarriers[cCarrierIndexOut]-cCarriers[index]);
}
return product;
}
private Matrix resort(Matrix matrix) {
Matrix m = new Matrix(matrix.getRowDimension(), matrix.getColumnDimension());
for (int i = 0; i < matrix.getRowDimension(); i++) {
for (int j = 0; j < matrix.getColumnDimension(); j++) {
m.set(matrix.getRowDimension()-1-i, j, matrix.get(i, j));
}
}
return m;
}
public double[] getAssembledValuesMaxDegrees(double[] usedData, int maxDegrees){
return assembleAllCarriers(usedData, calculateCCarrierValuesMaxDegrees(usedData, maxDegrees));
}
public double[] getAssembledValuesMaxPower(double[] usedData, double maxPowerCC){
return assembleAllCarriers(usedData, calculateCCarrierValuesMaxPower(usedData, maxPowerCC));
}
public double[] getAssembledValuesMaxPowerAndMaxDegrees(double[] usedData, double maxPowerCC, int maxDegrees){
return assembleAllCarriers(usedData, calculateCCarrierValuesMaxPowerAndMaxDegrees(usedData, maxPowerCC, maxDegrees));
}
public double[] assembleAllCarriers(double[] usedData, double[] cCarrierData) {
double[] allData = new double[usedData.length + cCarrierData.length];
for (int i = 0; i < usedCarriers.length; i++) {
allData[usedCarriers[i]] = usedData[i];
}
for (int i = 0; i < cCarriers.length; i++) {
allData[cCarriers[i]] = cCarrierData[i];
}
return allData;
}
public double[] calculateCCarrierValuesMaxDegrees(double[] usedData, int maxDegrees){
double[] cCarriersData = new double[cCarriers.length];
for (int degree = 0; degree < Math.min(cCarriers.length, maxDegrees); degree++) {
double value = getDegree(usedData, degree);
addValue(value, degree, cCarriersData);
}
return cCarriersData;
}
public double[] calculateCCarrierValuesMaxPower(double[] usedData, double maxPowerCC){
return calculateCCarrierValuesMaxPowerAndMaxDegrees(usedData, maxPowerCC, cCarriers.length);
}
public double[] calculateCCarrierValuesMaxPowerAndMaxDegrees(double[] usedData, double maxPowerCC, int maxDegrees){
double[] cCarriersData = new double[cCarriers.length];
if (maxDegrees>cCarriers.length)
maxDegrees = cCarriers.length;
double remainingAllowedPower = maxPowerCC;
for (int degree = 0; degree < maxDegrees; degree++) {
double value = getDegree(usedData, degree);
double pow = value * value;
//System.out.println("power=" + pow + " remainingAllowedPower=" + remainingAllowedPower);
if (pow>=remainingAllowedPower){
double factor = Math.sqrt(remainingAllowedPower / pow);
addValue(value*factor, degree, cCarriersData);
return cCarriersData;
}
addValue(value, degree, cCarriersData);
remainingAllowedPower = remainingAllowedPower - pow;
}
return cCarriersData;
}
private void addValue(double value, int degree, double[] cCarriersData) {
for (int i = 0; i < cCarriersData.length; i++) {
cCarriersData[i] = cCarriersData[i] + value * degreeToCCarrierMatrix.get(i, degree);
}
}
private double getDegree(double[] usedData, int degree) {
double sum = 0;
for (int i = 0; i < usedData.length; i++) {
sum += usedToDegreeMatrix.get(degree, i) * usedData[i];
}
return sum;
}
public static void main(String[] args) {
int allCarriers = 32;
Set<Integer> cancellationCarriers = new HashSet<Integer>();
cancellationCarriers.add(0);
cancellationCarriers.add(1);
cancellationCarriers.add(allCarriers-2);
cancellationCarriers.add(allCarriers-1);
PowerControlledCC cancellationCarrier = new PowerControlledCC(allCarriers, cancellationCarriers);
Matrix directCCMatrix = polyofdm.cc.full.FullCC.createCancellationMatrix(allCarriers, cancellationCarriers);
Matrix reducedPowerCCMatrix = cancellationCarrier.degreeToCCarrierMatrix.times(cancellationCarrier.usedToDegreeMatrix);
System.out.println("directCCMatrix");
directCCMatrix.print(15, 10);
System.out.println("reducedPowerCCMatrix");
reducedPowerCCMatrix.print(15, 10);
System.out.println("minus");
directCCMatrix.minus(reducedPowerCCMatrix).print(15, 10);
double[] usedData = new double[allCarriers-4];
usedData[0] = 1;
double[] cCarrierData = cancellationCarrier.calculateCCarrierValuesMaxDegrees(usedData, 10000);
System.out.println("ccarriers=" + Arrays.toString(cCarrierData));
double norm = 0;
for (int i = 0; i < cCarrierData.length; i++) {
norm += cCarrierData[i] * cCarrierData[i];
}
System.out.println("norm=" + norm);
System.out.println("allCarriers=" + Arrays.toString(cancellationCarrier.getAssembledValuesMaxDegrees(usedData, 10000)));
}
private static double power(double d, int degree) {
if (degree>1)
return d * power(d, degree-1);
else if (degree==1)
return d;
else if (degree==0)
return 1;
else
throw new IllegalArgumentException();
}
private static void validateDefinition(int allCarriers, Set<Integer> cancellationCarriers) {
for (Integer i : cancellationCarriers) {
int intValue = i.intValue();
if (intValue>=allCarriers)
throw new IllegalArgumentException("CancellationCarrier is given with i=" + i + " but this >= all (" + allCarriers + ')');
if (intValue<0)
throw new IllegalArgumentException("CancellationCarrier is given with i=" + i + " but this is < 0");
}
}
private static int[] getUsedCarriers(int allCarriers,
Set<Integer> cancellationCarriers) {
int[] usedCarriers = new int[allCarriers-cancellationCarriers.size()];
int counter = 0;
for (int pos = 0; pos < allCarriers; pos++) {
if (!cancellationCarriers.contains(pos))
usedCarriers[counter++] = pos;
}
return usedCarriers;
}
private static int[] getCancellationCarriers(int allCarriers,
Set<Integer> cancellationCarriers) {
int[] cCarriers = new int[cancellationCarriers.size()];
int counter = 0;
for (int pos = 0; pos < allCarriers; pos++) {
if (cancellationCarriers.contains(pos))
cCarriers[counter++] = pos;
}
return cCarriers;
}
}