1 | package geniusweb.ip.general;
|
---|
2 |
|
---|
3 | import java.math.BigDecimal;
|
---|
4 | import java.util.Random;
|
---|
5 |
|
---|
6 | public class RandomPartition {
|
---|
7 |
|
---|
8 | private int n;
|
---|
9 | private double[][] probabilityOfNew;
|
---|
10 |
|
---|
11 | public RandomPartition(int n) {
|
---|
12 | this.n = n;
|
---|
13 | this.calculateWeights(n);
|
---|
14 | }
|
---|
15 |
|
---|
16 | // random partition of numbers (0, 1, ..., n-1)
|
---|
17 | public int[] get() {
|
---|
18 | int partition[] = new int[n];
|
---|
19 |
|
---|
20 | Random randomGenerator = new Random();
|
---|
21 | int coalitionsCount = 1;
|
---|
22 | partition[0] = 1;
|
---|
23 | for (int i = 1; i < n; ++i) {
|
---|
24 | if (randomGenerator
|
---|
25 | .nextDouble() < this.probabilityOfNew[i][coalitionsCount]) {
|
---|
26 | partition[i] = coalitionsCount + 1;
|
---|
27 | ++coalitionsCount;
|
---|
28 | } else
|
---|
29 | partition[i] = randomGenerator.nextInt(coalitionsCount) + 1;
|
---|
30 | }
|
---|
31 |
|
---|
32 | // Convert the partition to a coalition structure, where every coalition
|
---|
33 | // is a number in which true bits represent the members
|
---|
34 | int[] coalitionStructure = new int[coalitionsCount];
|
---|
35 | for (int i = 0; i < coalitionsCount; i++) {
|
---|
36 | coalitionStructure[i] = 0;
|
---|
37 | }
|
---|
38 | for (int i = 0; i < n; i++) {
|
---|
39 | coalitionStructure[partition[i] - 1] += (1 << i); // add agent "i+1"
|
---|
40 | // to the
|
---|
41 | // coalition
|
---|
42 | }
|
---|
43 |
|
---|
44 | return coalitionStructure;
|
---|
45 | }
|
---|
46 |
|
---|
47 | private void calculateWeights(int n) {
|
---|
48 | BigDecimal[][] weights = new BigDecimal[n + 1][n + 1];
|
---|
49 | double[][] weightsDouble = new double[n + 1][n + 1];
|
---|
50 | this.probabilityOfNew = new double[n + 1][n + 1];
|
---|
51 |
|
---|
52 | weights[0][0] = BigDecimal.ONE;
|
---|
53 | weightsDouble[0][0] = 1;
|
---|
54 | BigDecimal bellNInverse = BigDecimal.ONE.divide(this.getBellNumber(n),
|
---|
55 | 500, BigDecimal.ROUND_UP);
|
---|
56 | for (int i = 1; i <= n; ++i) {
|
---|
57 | weights[n][i] = bellNInverse;
|
---|
58 | weightsDouble[n][i] = weights[n][i].doubleValue();
|
---|
59 | }
|
---|
60 |
|
---|
61 | for (int j = n - 1; j >= 1; --j) {
|
---|
62 | for (int k = 1; k <= j; ++k) {
|
---|
63 | weights[j][k] = weights[j + 1][k].multiply(new BigDecimal(k))
|
---|
64 | .add(weights[j + 1][k + 1]);
|
---|
65 | weightsDouble[j][k] = weights[j][k].doubleValue();
|
---|
66 | this.probabilityOfNew[j][k] = weights[j + 1][k + 1]
|
---|
67 | .divide(weights[j][k], 500, BigDecimal.ROUND_UP)
|
---|
68 | .doubleValue();
|
---|
69 | }
|
---|
70 | }
|
---|
71 | }
|
---|
72 |
|
---|
73 | private BigDecimal getBellNumber(int n) {
|
---|
74 | BigDecimal[] binomials;
|
---|
75 | BigDecimal[] bell = new BigDecimal[n + 1];
|
---|
76 | bell[0] = BigDecimal.ONE;
|
---|
77 | bell[1] = BigDecimal.ONE;
|
---|
78 |
|
---|
79 | for (int i = 2; i <= n; ++i) {
|
---|
80 | bell[i] = BigDecimal.ZERO;
|
---|
81 | binomials = computeBinomials(i - 1);
|
---|
82 | for (int k = 0; k < i; ++k)
|
---|
83 | bell[i] = bell[i].add(bell[k].multiply(binomials[k]));
|
---|
84 | }
|
---|
85 |
|
---|
86 | return bell[n];
|
---|
87 | }
|
---|
88 |
|
---|
89 | private BigDecimal[] computeBinomials(int n) {
|
---|
90 | BigDecimal[] binomials = new BigDecimal[n + 1];
|
---|
91 |
|
---|
92 | binomials[0] = BigDecimal.ONE;
|
---|
93 | for (int i = 1; i <= Math.floor(n / 2); ++i) {
|
---|
94 | binomials[i] = binomials[i - 1].multiply(new BigDecimal(n - i + 1))
|
---|
95 | .divide(new BigDecimal(i), 100, BigDecimal.ROUND_UP);
|
---|
96 | }
|
---|
97 | for (int i = (int) Math.floor(n / 2) + 1; i <= n; ++i)
|
---|
98 | binomials[i] = binomials[n - i];
|
---|
99 |
|
---|
100 | return binomials;
|
---|
101 | }
|
---|
102 |
|
---|
103 | }
|
---|