I have some random combinations of numbers pairs
(where numbers range from 1
to some ntest
) and weights to them weights
, merged into weightspairs
. I need to generate n/2
fully distinct pairs (such that each number is repeated in the generated set only once) using RandomSample/RandomChoice
.
I do this iteratively: generate the random combination, remove all occurrences of the numbers from the random combination from weightspairs
, and repeat:
ntest = 100;
pairs = Subsets[Range[ntest] // N, {2}] // Developer`ToPackedArray;
weights = RandomReal[{0, 1}, Length[pairs]];
weightspairs = Join[Partition[weights, 1], pairs, 2];
Do[
generatedPairsStep =
RandomSample[weightspairs[[All, 1]] -> weightspairs, 1];
If[i == 1,
pairssampling = generatedPairsStep,
pairssampling = Join[pairssampling, generatedPairsStep];
];
nlist = Drop[pairssampling, 1];
nlist = Flatten[pairssampling[[All, {2, 3}]]] // Sort;
matchesNList[row_] :=
MemberQ[nlist, row[[2]]] || MemberQ[nlist, row[[3]]];
weightspairs = DeleteCases[weightspairs, _?matchesNList];
If[Length[weightspairs] == 0, Break[]]
, {i, 1, ntest/2, 1}] // AbsoluteTiming
The method is slow, taking around ~1 second, and I need to consider a much larger ntest
. It is clear that some part of the code may be compiled, but the problem is that the approach itself is not optimal, especially in the part DeleteCases
.
Could you please tell me how to speed it up?
Edit
The following code works much faster, although it is still algorithmically poor (the time scales as ntest^3
):
compiledsel =
Compile[{{data, _Real, 2}, {nlist, _Real, 1}},
Select[data, ! MemberQ[nlist, #[[2]]] && !
MemberQ[nlist, #[[3]]] &], CompilationTarget -> "C",
RuntimeOptions -> "Speed", RuntimeAttributes -> {Listable},
Parallelization -> True];
ntest = 400;
pairs = Subsets[Range[ntest] // N, {2}] //
Developer`ToPackedArray; // AbsoluteTiming
weights = RandomReal[{0, 1}, Length[pairs]];
weightspairs = Join[Partition[weights, 1], pairs, 2];
nseed = ntest/2;
Do[
generatedPairsStep =
RandomChoice[weightspairs[[All, 1]] -> weightspairs, nseed] //
RandomSample;
par = {{}};
nTempList = {};
Do[If[! MemberQ[nTempList, generatedPairsStep[[m]][[2]]] && !
MemberQ[nTempList, generatedPairsStep[[m]][[3]]],
par = Join[par, {generatedPairsStep[[m]]}];
nTempList = Join[nTempList, Drop[generatedPairsStep[[m]], 1]]];
, {m, 1, nseed, 1}];
If[i == 1,
pairssampling = Drop[par, 1],
pairssampling = Join[pairssampling, Drop[par, 1]];
];
nlist = nTempList;
weightspairs =
compiledsel[weightspairs, nlist] // Developer`ToPackedArray;
If[Length[weightspairs] == 0, Break[]]
, {i, 1, ntest/2, 1}] // AbsoluteTiming
Here, however, I sample the pairs not one-by-one, but a much larger amount of times.
// N
on the second line - they're just integers. $\endgroup$g = Graph[UndirectedEdge @@@ pairs, EdgeWeight -> weights]; FindEdgeCover[g]
$\endgroup$