mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-22 22:45:21 +01:00
Add optimized permutation algo
WIP, needs more tests, comments, clean up....
This commit is contained in:
parent
18476e48b2
commit
54e280c78d
3 changed files with 104 additions and 19 deletions
|
@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@ -53,8 +54,53 @@ public class PermutationUtil {
|
||||||
return altered;
|
return altered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T, R> List<T> findMatchingPermutation(R targetValue,
|
||||||
|
List<T> list,
|
||||||
|
BiFunction<R, List<T>, Boolean> predicate,
|
||||||
|
int maxIterations) {
|
||||||
|
if (predicate.apply(targetValue, list)) {
|
||||||
|
return list;
|
||||||
|
} else {
|
||||||
|
return findMatchingPermutation(targetValue,
|
||||||
|
list,
|
||||||
|
new ArrayList<>(),
|
||||||
|
predicate,
|
||||||
|
maxIterations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T, R> List<T> findMatchingPermutation(R targetValue,
|
||||||
|
List<T> list,
|
||||||
|
List<List<T>> lists,
|
||||||
|
BiFunction<R, List<T>, Boolean> predicate,
|
||||||
|
int maxIterations) {
|
||||||
|
|
||||||
|
if (maxIterations == 0) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
maxIterations--;
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
List<T> newList = new ArrayList<>(list);
|
||||||
|
newList.remove(i);
|
||||||
|
|
||||||
|
// We want to avoid testing duplicates
|
||||||
|
if (!lists.contains(newList)) {
|
||||||
|
if (predicate.apply(targetValue, newList)) {
|
||||||
|
return newList;
|
||||||
|
} else {
|
||||||
|
lists.add(newList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<T> nextList = lists.remove(0);
|
||||||
|
return findMatchingPermutation(targetValue, nextList, lists, predicate, maxIterations);
|
||||||
|
}
|
||||||
|
|
||||||
//TODO optimize algorithm so that it starts from all objects and goes down instead starting with from the bottom.
|
//TODO optimize algorithm so that it starts from all objects and goes down instead starting with from the bottom.
|
||||||
// That should help that we are not hitting the iteration limit so easily.
|
// That should help that we are not hitting the iteration limit so easily.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all possible permutations of a give sorted list ignoring duplicates.
|
* Returns a list of all possible permutations of a give sorted list ignoring duplicates.
|
||||||
* E.g. List [A,B,C] results in this list of permutations: [[A], [B], [A,B], [C], [A,C], [B,C], [A,B,C]]
|
* E.g. List [A,B,C] results in this list of permutations: [[A], [B], [A,B], [C], [A,C], [B,C], [A,B,C]]
|
||||||
|
|
|
@ -21,15 +21,19 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class PermutationTest {
|
public class PermutationTest {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
// @Test
|
||||||
public void testGetPartialList() {
|
public void testGetPartialList() {
|
||||||
String blindVote0 = "blindVote0";
|
String blindVote0 = "blindVote0";
|
||||||
String blindVote1 = "blindVote1";
|
String blindVote1 = "blindVote1";
|
||||||
|
@ -96,6 +100,34 @@ public class PermutationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
public void testFindMatchingPermutation() {
|
||||||
|
String a = "A";
|
||||||
|
String b = "B";
|
||||||
|
String c = "C";
|
||||||
|
String d = "D";
|
||||||
|
String e = "E";
|
||||||
|
int limit = 1048575;
|
||||||
|
List<String> result;
|
||||||
|
List<String> list;
|
||||||
|
String targetValue;
|
||||||
|
List<String> expected;
|
||||||
|
BiFunction<String, List<String>, Boolean> predicate = (target, variationList) -> variationList.toString().equals(target);
|
||||||
|
|
||||||
|
list = Arrays.asList(a, b, c, d, e);
|
||||||
|
|
||||||
|
expected = Arrays.asList(a);
|
||||||
|
result = PermutationUtil.findMatchingPermutation(expected.toString(), list, predicate, limit);
|
||||||
|
assertTrue(expected.toString().equals(result.toString()));
|
||||||
|
|
||||||
|
|
||||||
|
expected = Arrays.asList(a, c, e);
|
||||||
|
result = PermutationUtil.findMatchingPermutation(expected.toString(), list, predicate, limit);
|
||||||
|
assertTrue(expected.toString().equals(result.toString()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @Test
|
||||||
public void testFindAllPermutations() {
|
public void testFindAllPermutations() {
|
||||||
String blindVote0 = "blindVote0";
|
String blindVote0 = "blindVote0";
|
||||||
String blindVote1 = "blindVote1";
|
String blindVote1 = "blindVote1";
|
||||||
|
@ -107,18 +139,23 @@ public class PermutationTest {
|
||||||
// findAllPermutations took 580 ms for 20 items and 1048575 iterations
|
// findAllPermutations took 580 ms for 20 items and 1048575 iterations
|
||||||
// findAllPermutations took 10 ms for 15 items and 32767 iterations
|
// findAllPermutations took 10 ms for 15 items and 32767 iterations
|
||||||
// findAllPermutations took 0 ms for 10 items and 1023 iterations
|
// findAllPermutations took 0 ms for 10 items and 1023 iterations
|
||||||
int limit = 1048575;
|
// int limit = 1048575;
|
||||||
|
int limit = 1048575000;
|
||||||
List<String> list;
|
List<String> list;
|
||||||
List<List<String>> expected;
|
List<List<String>> expected;
|
||||||
List<List<String>> result;
|
List<List<String>> result;
|
||||||
List<String> subList;
|
List<String> subList;
|
||||||
|
|
||||||
|
|
||||||
/* list = new ArrayList<>();
|
log.error("prep");
|
||||||
for (int i = 0; i < 20; i++) {
|
list = new ArrayList<>();
|
||||||
list.add("blindVote"+i);
|
for (int i = 0; i < 4; i++) {
|
||||||
|
list.add("blindVote" + i);
|
||||||
}
|
}
|
||||||
PermutationUtil.findAllPermutations(list, limit);*/
|
log.error("start");
|
||||||
|
|
||||||
|
PermutationUtil.findAllPermutations(list, limit);
|
||||||
|
log.error("end");
|
||||||
|
|
||||||
|
|
||||||
list = new ArrayList<>();
|
list = new ArrayList<>();
|
||||||
|
|
|
@ -77,6 +77,7 @@ import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -486,20 +487,20 @@ public class VoteResultService implements DaoStateListener, DaoSetupService {
|
||||||
private Optional<List<BlindVote>> findPermutatedListMatchingMajority(byte[] majorityVoteListHash) {
|
private Optional<List<BlindVote>> findPermutatedListMatchingMajority(byte[] majorityVoteListHash) {
|
||||||
List<BlindVote> list = BlindVoteConsensus.getSortedBlindVoteListOfCycle(blindVoteListService);
|
List<BlindVote> list = BlindVoteConsensus.getSortedBlindVoteListOfCycle(blindVoteListService);
|
||||||
long ts = System.currentTimeMillis();
|
long ts = System.currentTimeMillis();
|
||||||
List<List<BlindVote>> result = PermutationUtil.findAllPermutations(list, 1000000);
|
|
||||||
for (List<BlindVote> variation : result) {
|
BiFunction<byte[], List<BlindVote>, Boolean> predicate = (hash, variation) ->
|
||||||
if (isListMatchingMajority(majorityVoteListHash, variation, false)) {
|
isListMatchingMajority(hash, variation, false);
|
||||||
log.info("We found a variation of the blind vote list which matches the majority hash. variation={}",
|
|
||||||
variation);
|
List<BlindVote> result = PermutationUtil.findMatchingPermutation(majorityVoteListHash, list, predicate, 1000000);
|
||||||
log.info("findPermutatedListMatchingMajority for {} items took {} ms.",
|
log.info("findPermutatedListMatchingMajority for {} items took {} ms.",
|
||||||
list.size(), (System.currentTimeMillis() - ts));
|
list.size(), (System.currentTimeMillis() - ts));
|
||||||
return Optional.of(variation);
|
if (result.isEmpty()) {
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info("We did not find a variation of the blind vote list which matches the majority hash.");
|
log.info("We did not find a variation of the blind vote list which matches the majority hash.");
|
||||||
log.info("findPermutatedListMatchingMajority for {} items took {} ms.",
|
|
||||||
list.size(), (System.currentTimeMillis() - ts));
|
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
} else {
|
||||||
|
log.info("We found a variation of the blind vote list which matches the majority hash. variation={}", result);
|
||||||
|
return Optional.of(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isListMatchingMajority(byte[] majorityVoteListHash, List<BlindVote> list, boolean doLog) {
|
private boolean isListMatchingMajority(byte[] majorityVoteListHash, List<BlindVote> list, boolean doLog) {
|
||||||
|
@ -513,7 +514,8 @@ public class VoteResultService implements DaoStateListener, DaoSetupService {
|
||||||
return Arrays.equals(majorityVoteListHash, hashOfBlindVoteList);
|
return Arrays.equals(majorityVoteListHash, hashOfBlindVoteList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<EvaluatedProposal> getEvaluatedProposals(Set<DecryptedBallotsWithMerits> decryptedBallotsWithMeritsSet, int chainHeight) {
|
private Set<EvaluatedProposal> getEvaluatedProposals(Set<DecryptedBallotsWithMerits> decryptedBallotsWithMeritsSet,
|
||||||
|
int chainHeight) {
|
||||||
// We reorganize the data structure to have a map of proposals with a list of VoteWithStake objects
|
// We reorganize the data structure to have a map of proposals with a list of VoteWithStake objects
|
||||||
Map<Proposal, List<VoteWithStake>> resultListByProposalMap = getVoteWithStakeListByProposalMap(decryptedBallotsWithMeritsSet);
|
Map<Proposal, List<VoteWithStake>> resultListByProposalMap = getVoteWithStakeListByProposalMap(decryptedBallotsWithMeritsSet);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue