mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-22 06:41:41 +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.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
@ -53,8 +54,53 @@ public class PermutationUtil {
|
|||
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.
|
||||
// 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.
|
||||
* 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.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@Slf4j
|
||||
public class PermutationTest {
|
||||
|
||||
|
||||
@Test
|
||||
// @Test
|
||||
public void testGetPartialList() {
|
||||
String blindVote0 = "blindVote0";
|
||||
String blindVote1 = "blindVote1";
|
||||
|
@ -96,6 +100,34 @@ public class PermutationTest {
|
|||
}
|
||||
|
||||
@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() {
|
||||
String blindVote0 = "blindVote0";
|
||||
String blindVote1 = "blindVote1";
|
||||
|
@ -107,18 +139,23 @@ public class PermutationTest {
|
|||
// findAllPermutations took 580 ms for 20 items and 1048575 iterations
|
||||
// findAllPermutations took 10 ms for 15 items and 32767 iterations
|
||||
// findAllPermutations took 0 ms for 10 items and 1023 iterations
|
||||
int limit = 1048575;
|
||||
// int limit = 1048575;
|
||||
int limit = 1048575000;
|
||||
List<String> list;
|
||||
List<List<String>> expected;
|
||||
List<List<String>> result;
|
||||
List<String> subList;
|
||||
|
||||
|
||||
/* list = new ArrayList<>();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
list.add("blindVote"+i);
|
||||
log.error("prep");
|
||||
list = new ArrayList<>();
|
||||
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<>();
|
||||
|
|
|
@ -77,6 +77,7 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -486,20 +487,20 @@ public class VoteResultService implements DaoStateListener, DaoSetupService {
|
|||
private Optional<List<BlindVote>> findPermutatedListMatchingMajority(byte[] majorityVoteListHash) {
|
||||
List<BlindVote> list = BlindVoteConsensus.getSortedBlindVoteListOfCycle(blindVoteListService);
|
||||
long ts = System.currentTimeMillis();
|
||||
List<List<BlindVote>> result = PermutationUtil.findAllPermutations(list, 1000000);
|
||||
for (List<BlindVote> variation : result) {
|
||||
if (isListMatchingMajority(majorityVoteListHash, variation, false)) {
|
||||
log.info("We found a variation of the blind vote list which matches the majority hash. variation={}",
|
||||
variation);
|
||||
log.info("findPermutatedListMatchingMajority for {} items took {} ms.",
|
||||
list.size(), (System.currentTimeMillis() - ts));
|
||||
return Optional.of(variation);
|
||||
}
|
||||
}
|
||||
log.info("We did not find a variation of the blind vote list which matches the majority hash.");
|
||||
|
||||
BiFunction<byte[], List<BlindVote>, Boolean> predicate = (hash, variation) ->
|
||||
isListMatchingMajority(hash, variation, false);
|
||||
|
||||
List<BlindVote> result = PermutationUtil.findMatchingPermutation(majorityVoteListHash, list, predicate, 1000000);
|
||||
log.info("findPermutatedListMatchingMajority for {} items took {} ms.",
|
||||
list.size(), (System.currentTimeMillis() - ts));
|
||||
return Optional.empty();
|
||||
if (result.isEmpty()) {
|
||||
log.info("We did not find a variation of the blind vote list which matches the majority hash.");
|
||||
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) {
|
||||
|
@ -513,7 +514,8 @@ public class VoteResultService implements DaoStateListener, DaoSetupService {
|
|||
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
|
||||
Map<Proposal, List<VoteWithStake>> resultListByProposalMap = getVoteWithStakeListByProposalMap(decryptedBallotsWithMeritsSet);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue