// Lemma 4.1
private PermutationNetwork CreateBlockCorrectionNetwork(int blockBitLength, int unsortedness)
{
PermutationNetwork pn = new PermutationNetwork(1 << blockBitLength);
SortedSet <int> ySet = new SortedSet <int>(CalculationCache.generateY(blockBitLength));
Debug.Assert(ySet.Count <= 1 << unsortedness);
// augment Y with arbitrary elements
int ySize = 1 << (unsortedness + 1);
int blockSize = 1 << blockBitLength;
Random rand = new Random(0);
while (ySet.Count < ySize)
{
ySet.Add(rand.Next(blockSize));
}
// here our implementation differs from the paper. The paper first to extract Y then order the X by the permutation pi.
// Instead, we will order all of the inputs by the permutation pi, then map Y using the permutation pi and move X to the top of the block
// and Y to the bottom so that we can unshuffle X and add Y.
int[] pi = CalculationCache.generatePi(blockBitLength);
pn.AppendGate(new PermutationGate(pi), 0);
int[] mappedY = new int[ySize];
int i = 0;
foreach (var yElem in ySet)
{
mappedY[i++] = pi[yElem];
}
pn.AppendGate(PermutationGateFactory.CreateSplitGate(blockSize, mappedY, false), 0);
// we now want to unshuffle X into 2^(l+1) groups and add one element of Y to each group
pn.AppendGate(PermutationGateFactory.CreateUnshuffleGate(blockSize - ySize, ySize), 0);
pn.AppendGate(PermutationGateFactory.CreateMultiGroupInserterGate(blockSize, (blockSize / ySize) - 1, ySize), 0);
var treeInsertion = SortingNetworkFactory.CreateBinaryTreeInsertion(blockSize / ySize);
// use binary tree insertion to insert the elemnt we just added to each group
for (int j = 0; j < ySize; j++)
{
pn.AppendNetwork(treeInsertion.Clone() as PermutationNetwork, j * blockSize / ySize);
}
// now shuffle all of the lists back together
pn.AppendGate(PermutationGateFactory.CreateShuffleGate(blockSize, ySize), 0);
return(pn);
}