public void AppendNetwork(PermutationNetwork pn, int[] wires) { // append the provided network to this one. join wires[i] to i Debug.Assert(wires.Length == pn.WireCount); List <GateConnection> joins = new List <GateConnection>(); for (int i = 0; i < wires.Length; i++) { int wire = wires[i]; if (LastGateForWire[wire] != null && pn.FirstGateForWire[i] != null) { joins.Add(new GateConnection(LastGateForWire[wire], pn.FirstGateForWire[i])); } if (pn.LastGateForWire[i] != null) { LastGateForWire[wire] = pn.LastGateForWire[i]; } if (FirstGateForWire[wire] == null) { FirstGateForWire[wire] = pn.FirstGateForWire[i]; } WireGateList[wire].AddRange(pn.WireGateList[i]); } Circuit.JoinWith(pn.Circuit, joins); }
private PermutationNetwork CreateBorderSorter(int borderBitLength, int intraBlockSortQuality) { PermutationNetwork pn = new PermutationNetwork(1 << (borderBitLength + 1)); int borderSize = 1 << borderBitLength; int listCount = (1 << (intraBlockSortQuality + 1)); int listSize = borderSize / listCount; pn.AppendGate(PermutationGateFactory.CreateUnshuffleGate(borderSize, listCount), 0); pn.AppendGate(PermutationGateFactory.CreateUnshuffleGate(borderSize, listCount), borderSize); // merge the corresponding lists for (int i = 0; i < listCount; i++) { int[] wires = new int[listSize * 2]; for (int j = 0; i < listSize; i++) { wires[j] = i * listSize + j; wires[j + listSize] = wires[j] + borderSize; } pn.AppendNetwork(SortingNetworkFactory.CreateBitonicMerge(listSize * 2, false), wires); } // shuffle the lists back into the blocks pn.AppendGate(PermutationGateFactory.CreateShuffleGate(borderSize, listCount), 0); pn.AppendGate(PermutationGateFactory.CreateShuffleGate(borderSize, listCount), borderSize); return(pn); }
// 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); }
// Lemma 4.2 private PermutationNetwork CreateTournament(int sortInaccuracy) { PermutationNetwork pn = new PermutationNetwork(1 << K); int blockSize = 1 << sortInaccuracy; // for the permutation rho PermutationGate permuteGate = new PermutationGate(GenerateArbitraryPermutation(blockSize)); pn.AppendGate(permuteGate.Copy() as Gate, 0); pn.AppendNetwork(SortingNetworkFactory.CreateButterflyTournament(blockSize), 0); return(pn); }
public void AppendNetwork(PermutationNetwork pn, int startWire) { Debug.Assert(startWire + pn.WireCount <= WireCount); // wasteful but good enough for now int[] mapping = new int[pn.WireCount]; for (int i = 0; i < pn.WireCount; i++) { mapping[i] = startWire + i; } AppendNetwork(pn, mapping); }
public static PermutationNetwork CreateButterflyTournamentRound(int wireCount) { Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); // we want to join every wire to its corresponding wire on the other half using a compare and swap gate for (int i = 0; i < wireCount / 2; i++) { pn.AppendGate(new ComputationGate(ComputationGateType.COMPARE_AND_SWAP), new int[] { i, i + wireCount / 2 }); } return(pn); }
public static PermutationNetwork CreateBitonicSort(int wireCount, bool invertOrder) { Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); if (wireCount >= 4) { pn.AppendNetwork(CreateBitonicSort(wireCount / 2, false), 0); pn.AppendNetwork(CreateBitonicSort(wireCount / 2, true), wireCount / 2); } pn.AppendNetwork(CreateBitonicMerge(wireCount, invertOrder), 0); return(pn); }
public static PermutationNetwork CreateBitonicSort(int wireCount, bool invertOrder) { Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); if (wireCount >= 4) { pn.AppendNetwork(CreateBitonicSort(wireCount / 2, false), 0); pn.AppendNetwork(CreateBitonicSort(wireCount / 2, true), wireCount / 2); } pn.AppendNetwork(CreateBitonicMerge(wireCount, invertOrder), 0); return pn; }
public static PermutationNetwork CreateBitonicSplit(int wireCount, bool invertOrder) { Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); for (int i = 0; i < wireCount / 2; i++) { pn.AppendGate(new ComputationGate(ComputationGateType.COMPARE_AND_SWAP), new int[] { i, i + wireCount / 2 }); if (invertOrder) { pn.AppendGate(PermutationGateFactory.CreateSwapGate(), new int[] { i, i + wireCount / 2 }); } } return(pn); }
// Lemma 4.4 private PermutationNetwork CreateBlockNeighborSorter(int blockBitLength, int borderBitLength, int intraBlockSortQuality) { PermutationNetwork pn = new PermutationNetwork(1 << K); int blockSize = 1 << blockBitLength; int blockCount = 1 << (K - blockBitLength); int borderSize = 1 << borderBitLength; PermutationNetwork borderSorter = CreateBorderSorter(borderBitLength, intraBlockSortQuality); for (int i = 0; i < blockCount - 1; i++) { pn.AppendNetwork(borderSorter.Clone() as PermutationNetwork, i * blockSize + (blockSize - borderSize)); } return(pn); }
// Lemma 4.3 private PermutationNetwork CreateFinalSorter(int blockBitLength) { PermutationNetwork pn = new PermutationNetwork(1 << K); int blockSize = 1 << blockBitLength; int blockCount = 1 << (K - blockBitLength); // sort each block, alternate orders for bitonic merge coming up var bitonicSort = SortingNetworkFactory.CreateBitonicSort(blockSize, false); for (int i = 0; i < blockCount; i++) { pn.AppendNetwork(bitonicSort, i * blockSize); if (i % 2 == 1) { pn.AppendGate(PermutationGateFactory.CreateInvertGate(blockSize), i * blockSize); } } PermutationNetwork twoBlockMerge = SortingNetworkFactory.CreateBitonicMerge(blockSize * 2, false); // merge each block with the one next to it. alternate ordern for bitonic merge coming up var bitonicMerge = SortingNetworkFactory.CreateBitonicMerge(blockSize * 2, false); for (int i = 0; i < blockCount; i += 2) { pn.AppendNetwork(bitonicMerge.Clone() as PermutationNetwork, i * blockSize); if ((i / 2) % 2 == 1) { pn.AppendGate(PermutationGateFactory.CreateInvertGate(2 * blockSize), i * blockSize); } } // do another round of merges, this time offset by 1 for (int i = 1; i < blockCount; i += 2) { pn.AppendNetwork(bitonicMerge.Clone() as PermutationNetwork, i * blockSize); } // the last block will be inverted, so uninvert it pn.AppendGate(PermutationGateFactory.CreateInvertGate(blockSize), (blockCount - 1) * blockSize); return(pn); }
// the subsequent rounds private LPSortingNetwork(int k, int l, LPSortingCalculationCache calculationCache) : base(1 << k) { Console.WriteLine(k + " " + l); CalculationCache = calculationCache; K = k; if (l <= (int)Math.Floor(gamma * (l + 2)) + c + 5) { // if we would get worse by doing the procedure, then finish if (k <= l) { AppendNetwork(SortingNetworkFactory.CreateBitonicSort(1 << K, false), 0); } else { // Apply Lemma 4.3 AppendNetwork(CreateFinalSorter(l), 0); } } else { // Apply Lemma 4.2 PermutationNetwork tournament = CreateTournament(l + 2); // Apply Lemma 4.1 PermutationNetwork tournamentCorrecter = CreateBlockCorrectionNetwork(l + 2, (int)Math.Floor(gamma * (l + 2)) + c); for (int i = 0; i < 1 << (k - (l + 2)); i++) { AppendNetwork(tournament.Clone() as PermutationNetwork, i * (1 << (l + 2))); AppendNetwork(tournamentCorrecter.Clone() as PermutationNetwork, i * (1 << (l + 2))); } // Apply Lemma 4.4 PermutationNetwork neighborCorrecter = CreateBlockNeighborSorter(l + 2, l + 1, (int)Math.Floor(gamma * (l + 2)) + c + 2); AppendNetwork(neighborCorrecter, 0); AppendNetwork(new LPSortingNetwork(k, (int)Math.Floor(gamma * (l + 2)) + c + 5, CalculationCache), 0); } }
public object Clone() { var clone = new PermutationNetwork(WireCount); Dictionary <Gate, Gate> mapping; clone.Circuit = Circuit.Clone(out mapping) as Circuit; for (int i = 0; i < WireCount; i++) { if (FirstGateForWire[i] != null) { clone.FirstGateForWire[i] = new InputGateAddress(mapping[FirstGateForWire[i].Gate], FirstGateForWire[i].Port); } if (LastGateForWire[i] != null) { clone.LastGateForWire[i] = new OutputGateAddress(mapping[LastGateForWire[i].Gate], LastGateForWire[i].Port); } } return(clone); }
public static PermutationNetwork CreateButterflyTournament(int wireCount) { Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); if (wireCount == 1) { return(pn); } pn.AppendNetwork(CreateButterflyTournamentRound(wireCount), 0); // recursively construct the butterfly if (wireCount > 2) { pn.AppendNetwork(CreateButterflyTournament(wireCount / 2), 0); pn.AppendNetwork(CreateButterflyTournament(wireCount / 2), wireCount / 2); } return(pn); }
public static PermutationNetwork CreateBinaryTreeInsertion(int wireCount) { // assume that the first input wire is the location of the unsorted element Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); if (wireCount == 1) { return(pn); } pn.AppendGate(new ComputationGate(ComputationGateType.COMPARE_AND_SWAP), new int[] { 0, wireCount / 2 }); if (wireCount > 2) { pn.AppendNetwork(CreateBinaryTreeInsertion(wireCount / 2), 0); pn.AppendNetwork(CreateBinaryTreeInsertion(wireCount / 2), wireCount / 2); } return(pn); }
public static PermutationNetwork CreateBinaryTreeInsertion(int wireCount) { // assume that the first input wire is the location of the unsorted element Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); if (wireCount == 1) { return pn; } pn.AppendGate(new ComputationGate(ComputationGateType.COMPARE_AND_SWAP), new int[] { 0, wireCount / 2 }); if (wireCount > 2) { pn.AppendNetwork(CreateBinaryTreeInsertion(wireCount / 2), 0); pn.AppendNetwork(CreateBinaryTreeInsertion(wireCount / 2), wireCount / 2); } return pn; }
public static PermutationNetwork CreateButterflyTournament(int wireCount) { Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); if (wireCount == 1) return pn; pn.AppendNetwork(CreateButterflyTournamentRound(wireCount), 0); // recursively construct the butterfly if (wireCount > 2) { pn.AppendNetwork(CreateButterflyTournament(wireCount / 2), 0); pn.AppendNetwork(CreateButterflyTournament(wireCount / 2), wireCount / 2); } return pn; }
public static PermutationNetwork CreateBitonicSplit(int wireCount, bool invertOrder) { Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); for (int i = 0; i < wireCount / 2; i++) { pn.AppendGate(new ComputationGate(ComputationGateType.COMPARE_AND_SWAP), new int[] { i, i + wireCount / 2 }); if (invertOrder) pn.AppendGate(PermutationGateFactory.CreateSwapGate(), new int[] { i, i + wireCount / 2 }); } return pn; }
// 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; }
public object Clone() { var clone = new PermutationNetwork(WireCount); Dictionary<Gate, Gate> mapping; clone.Circuit = Circuit.Clone(out mapping) as Circuit; for (int i = 0; i < WireCount; i++) { if (FirstGateForWire[i] != null) clone.FirstGateForWire[i] = new InputGateAddress(mapping[FirstGateForWire[i].Gate], FirstGateForWire[i].Port); if (LastGateForWire[i] != null) clone.LastGateForWire[i] = new OutputGateAddress(mapping[LastGateForWire[i].Gate], LastGateForWire[i].Port); } return clone; }
public static PermutationNetwork CreateButterflyTournamentRound(int wireCount) { Debug.Assert(SortingNetwork.isPowerOfTwo((uint)wireCount)); PermutationNetwork pn = new PermutationNetwork(wireCount); // we want to join every wire to its corresponding wire on the other half using a compare and swap gate for (int i = 0; i < wireCount / 2; i++) { pn.AppendGate(new ComputationGate(ComputationGateType.COMPARE_AND_SWAP), new int[] { i, i + wireCount / 2 }); } return pn; }
public void AppendNetwork(PermutationNetwork pn, int[] wires) { // append the provided network to this one. join wires[i] to i Debug.Assert(wires.Length == pn.WireCount); List<GateConnection> joins = new List<GateConnection>(); for (int i = 0; i < wires.Length; i++) { int wire = wires[i]; if (LastGateForWire[wire] != null && pn.FirstGateForWire[i] != null) { joins.Add(new GateConnection(LastGateForWire[wire], pn.FirstGateForWire[i])); } if (pn.LastGateForWire[i] != null) { LastGateForWire[wire] = pn.LastGateForWire[i]; } if (FirstGateForWire[wire] == null) { FirstGateForWire[wire] = pn.FirstGateForWire[i]; } WireGateList[wire].AddRange(pn.WireGateList[i]); } Circuit.JoinWith(pn.Circuit, joins); }
/* public static void SetupSimpleCircuitEvaluation(Quorum quorum) { int n = quorum.Size; var polyDeg = (int)Math.Ceiling(n / 3.0) - 1; Debug.Assert((n & (n - 1)) == 0); // is power of 2 network = new LPSortingNetwork(n); IList<BigZp>[] shares = new IList<BigZp>[n]; for (int i = 0; i < n; i++) shares[i] = BigShamirSharing.Share(new BigZp(prime, 500 - 2*i), n, polyDeg); foreach (var id in quorum.Members) { Dictionary<InputGateAddress, Share<BigZp>> inShares = new Dictionary<InputGateAddress, Share<BigZp>>(); int i = 0; foreach (var inAddr in network.Circuit.InputAddrs) { inShares[inAddr] = new Share<BigZp>(shares[i][id]); i++; } TestParty<IDictionary<OutputGateAddress, Share<BigZp>>> party = new TestParty<IDictionary<OutputGateAddress, Share<BigZp>>>(); party.UnderTest = new SecureGroupCircuitEvaluation(party, quorum.Clone() as Quorum, network.Circuit, inShares); NetSimulator.RegisterParty(party); } } */ public static void SetupMultiQuorumCircuitEvaluation(Quorum bigQuorum) { int n = bigQuorum.Size; int qSize = n / 2; var polyDeg = (int)Math.Ceiling(qSize / 3.0) - 1; var quorums = new List<Quorum>(); quorums.Add(new Quorum(0, 0, qSize)); quorums.Add(new Quorum(1, qSize, 2*qSize)); Debug.Assert((n & (n - 1)) == 0); // is power of 2 network = new LPSortingNetwork(n); //network = SortingNetworkFactory.CreateButterflyTournamentRound(n); network.CollapsePermutationGates(); IList<BigZp>[] shares = new IList<BigZp>[n]; for (int i = 0; i < n; i++) shares[i] = BigShamirSharing.Share(new BigZp(prime, 500 - 2 * i), qSize, polyDeg); Dictionary<Gate, Quorum> gqmapping = new Dictionary<Gate, Quorum>(); for (int i = 0; i < network.Circuit.TopologicalOrder.Count; i++) gqmapping[network.Circuit.TopologicalOrder[i]] = quorums[i]; foreach (var id in bigQuorum.Members) { Dictionary<InputGateAddress, Share<BigZp>> inShares = new Dictionary<InputGateAddress, Share<BigZp>>(); int i = 0; foreach (var inAddr in network.Circuit.InputAddrs) { inShares[inAddr] = new Share<BigZp>(shares[i][id % 4]); i++; } TestParty<IDictionary<OutputGateAddress, Share<BigZp>>> party = new TestParty<IDictionary<OutputGateAddress, Share<BigZp>>>(); Quorum[] quorumsClone = quorums.Select(a => a.Clone() as Quorum).ToArray(); party.UnderTest = new SecureMultiQuorumCircuitEvaluation<Share<BigZp>>(party, quorumsClone[id / qSize], quorumsClone, ProtocolIdGenerator.GenericIdentifier(0), network.Circuit, inShares, new BigZpShareGateEvaluationFactory(prime), gqmapping, prime); NetSimulator.RegisterParty(party); } }
// Lemma 4.4 private PermutationNetwork CreateBlockNeighborSorter(int blockBitLength, int borderBitLength, int intraBlockSortQuality) { PermutationNetwork pn = new PermutationNetwork(1 << K); int blockSize = 1 << blockBitLength; int blockCount = 1 << (K - blockBitLength); int borderSize = 1 << borderBitLength; PermutationNetwork borderSorter = CreateBorderSorter(borderBitLength, intraBlockSortQuality); for (int i = 0; i < blockCount - 1; i++) { pn.AppendNetwork(borderSorter.Clone() as PermutationNetwork, i * blockSize + (blockSize - borderSize)); } return pn; }
private PermutationNetwork CreateBorderSorter(int borderBitLength, int intraBlockSortQuality) { PermutationNetwork pn = new PermutationNetwork(1 << (borderBitLength + 1)); int borderSize = 1 << borderBitLength; int listCount = (1 << (intraBlockSortQuality + 1)); int listSize = borderSize / listCount; pn.AppendGate(PermutationGateFactory.CreateUnshuffleGate(borderSize, listCount), 0); pn.AppendGate(PermutationGateFactory.CreateUnshuffleGate(borderSize, listCount), borderSize); // merge the corresponding lists for (int i = 0; i < listCount; i++) { int[] wires = new int[listSize * 2]; for (int j = 0; i < listSize; i++) { wires[j] = i * listSize + j; wires[j + listSize] = wires[j] + borderSize; } pn.AppendNetwork(SortingNetworkFactory.CreateBitonicMerge(listSize * 2, false), wires); } // shuffle the lists back into the blocks pn.AppendGate(PermutationGateFactory.CreateShuffleGate(borderSize, listCount), 0); pn.AppendGate(PermutationGateFactory.CreateShuffleGate(borderSize, listCount), borderSize); return pn; }
// Lemma 4.3 private PermutationNetwork CreateFinalSorter(int blockBitLength) { PermutationNetwork pn = new PermutationNetwork(1 << K); int blockSize = 1 << blockBitLength; int blockCount = 1 << (K - blockBitLength); // sort each block, alternate orders for bitonic merge coming up var bitonicSort = SortingNetworkFactory.CreateBitonicSort(blockSize, false); for (int i = 0; i < blockCount; i++) { pn.AppendNetwork(bitonicSort, i * blockSize); if (i % 2 == 1) pn.AppendGate(PermutationGateFactory.CreateInvertGate(blockSize), i * blockSize); } PermutationNetwork twoBlockMerge = SortingNetworkFactory.CreateBitonicMerge(blockSize * 2, false); // merge each block with the one next to it. alternate ordern for bitonic merge coming up var bitonicMerge = SortingNetworkFactory.CreateBitonicMerge(blockSize * 2, false); for (int i = 0; i < blockCount; i+=2) { pn.AppendNetwork(bitonicMerge.Clone() as PermutationNetwork, i * blockSize); if ((i / 2) % 2 == 1) pn.AppendGate(PermutationGateFactory.CreateInvertGate(2 * blockSize), i * blockSize); } // do another round of merges, this time offset by 1 for (int i = 1; i < blockCount; i+=2) { pn.AppendNetwork(bitonicMerge.Clone() as PermutationNetwork, i * blockSize); } // the last block will be inverted, so uninvert it pn.AppendGate(PermutationGateFactory.CreateInvertGate(blockSize), (blockCount - 1) * blockSize); return pn; }
// Lemma 4.2 private PermutationNetwork CreateTournament(int sortInaccuracy) { PermutationNetwork pn = new PermutationNetwork(1 << K); int blockSize = 1 << sortInaccuracy; // for the permutation rho PermutationGate permuteGate = new PermutationGate(GenerateArbitraryPermutation(blockSize)); pn.AppendGate(permuteGate.Copy() as Gate, 0); pn.AppendNetwork(SortingNetworkFactory.CreateButterflyTournament(blockSize), 0); return pn; }