-
Notifications
You must be signed in to change notification settings - Fork 370
Feature: Improved CW Calculation #1451
Changes from 3 commits
a419063
855ec6a
9951d39
676eef4
2966d99
ccd5536
fbaf71d
10e3f16
77fde23
ed951f1
34ee23b
4953955
525d687
dba6828
1ae6a80
4d067a1
1b0aaff
29c40a0
babc42f
d410622
dfa4599
3f5d176
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,12 @@ | |
|
||
import java.util.ArrayDeque; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.Deque; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.Map; | ||
|
||
import org.apache.commons.collections4.CollectionUtils; | ||
import java.util.Set; | ||
|
||
import com.iota.iri.controllers.ApproveeViewModel; | ||
import com.iota.iri.controllers.TransactionViewModel; | ||
|
@@ -21,7 +21,10 @@ | |
import com.iota.iri.utils.collections.interfaces.UnIterableMap; | ||
|
||
/** | ||
* Calculates the weight recursively/on the fly instead of building the tree and calculating after | ||
* Calculates the weight recursively/on the fly | ||
* Used to create a weighted random walks. | ||
* | ||
* @see <a href="cumulative.md">https://github.com/alongalky/iota-docs/blob/master/cumulative.md</a> | ||
*/ | ||
public class RecursiveWeightCalculator implements RatingCalculator { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change name to CumulativeWeightCalculator |
||
|
||
|
@@ -40,9 +43,9 @@ public RecursiveWeightCalculator(Tangle tangle, SnapshotProvider snapshotProvide | |
|
||
@Override | ||
public UnIterableMap<HashId, Integer> calculate(Hash entryPoint) throws Exception { | ||
UnIterableMap<HashId, Integer> hashWeight = calculateRatingDfs(entryPoint); | ||
UnIterableMap<HashId, Integer> hashWeightMap = calculateRatingDfs(entryPoint); | ||
|
||
return hashWeight; | ||
return hashWeightMap; | ||
} | ||
|
||
private UnIterableMap<HashId, Integer> calculateRatingDfs(Hash entryPoint) throws Exception { | ||
|
@@ -54,15 +57,15 @@ private UnIterableMap<HashId, Integer> calculateRatingDfs(Hash entryPoint) throw | |
// Estimated capacity per depth, assumes 5 minute gap in between milestones, at 3tps | ||
UnIterableMap<HashId, Integer> hashWeight = createTxHashToCumulativeWeightMap( 5 * 60 * 3 * depth); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe call it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you changed it in one place, but you didn't change it in the others |
||
|
||
Map<Hash, HashSet<Hash>> txToDirectApprovers = new HashMap<>(); | ||
Map<Hash, Set<Hash>> txToDirectApprovers = new HashMap<>(); | ||
|
||
Deque<Hash> stack = new ArrayDeque<>(); | ||
stack.push(entryPoint); | ||
|
||
while (CollectionUtils.isNotEmpty(stack)) { | ||
while (!stack.isEmpty()) { | ||
Hash txHash = stack.peekLast(); | ||
|
||
HashSet<Hash> approvers = getTxDirectApproversHashes(txHash, txToDirectApprovers); | ||
Set<Hash> approvers = getTxDirectApproversHashes(txHash, txToDirectApprovers); | ||
if (null != approvers && (approvers.size() == 0 || hasAll(hashWeight, approvers, stack))) { | ||
approvers.add(txHash); | ||
hashWeight.put(txHash, getRating(approvers, txToDirectApprovers)); | ||
|
@@ -75,21 +78,36 @@ private UnIterableMap<HashId, Integer> calculateRatingDfs(Hash entryPoint) throw | |
return hashWeight; | ||
} | ||
|
||
private int getRating(HashSet<Hash> nonDupes, Map<Hash, HashSet<Hash>> txToDirectApprovers) throws Exception { | ||
Deque<Hash> stack = new ArrayDeque<>(nonDupes); | ||
while (CollectionUtils.isNotEmpty(stack)) { | ||
HashSet<Hash> approvers = getTxDirectApproversHashes(stack.pollLast(), txToDirectApprovers); | ||
/** | ||
* Gets the rating of a set, calculated by checking its approvers | ||
* | ||
* @param startingSet | ||
* @param txToDirectApproversCache | ||
* @return | ||
* @throws Exception | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fill in the |
||
*/ | ||
private int getRating(Set<Hash> startingSet, Map<Hash, Set<Hash>> txToDirectApproversCache) throws Exception { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change the name to Optional: |
||
Deque<Hash> stack = new ArrayDeque<>(startingSet); | ||
while (stack.isEmpty()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After seeing this test I ran the unit tests locally They failed... |
||
Set<Hash> approvers = getTxDirectApproversHashes(stack.pollLast(), txToDirectApproversCache); | ||
for (Hash hash : approvers) { | ||
if (nonDupes.add(hash)) { | ||
if (startingSet.add(hash)) { | ||
stack.add(hash); | ||
} | ||
} | ||
} | ||
|
||
return nonDupes.size(); | ||
return startingSet.size(); | ||
} | ||
|
||
private boolean hasAll(UnIterableMap<HashId, Integer> source, HashSet<Hash> requester, Deque<Hash> stack) { | ||
/** | ||
* | ||
* @param source | ||
* @param requester | ||
* @param stack | ||
* @return | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. empty javadoc? |
||
private boolean hasAll(UnIterableMap<HashId, Integer> source, Set<Hash> requester, Deque<Hash> stack) { | ||
for (Hash h : requester) { | ||
if (!source.containsKey(h) && !stack.contains(h)) { | ||
return false; | ||
|
@@ -99,21 +117,27 @@ private boolean hasAll(UnIterableMap<HashId, Integer> source, HashSet<Hash> requ | |
} | ||
|
||
/** | ||
* Finds the approvers of a transaction, and adds it to the txToDirectApprovers map if they werent there yet. | ||
* Finds the approvers of a transaction, and adds it to the txToDirectApprovers map if they weren't there yet. | ||
* | ||
* @param txHash The tx we find the approvers of | ||
* @param txToDirectApprovers The map we look in, and add to | ||
* @param fallback The map we check in before going in the database, can be <code>null</code> | ||
* @return | ||
* @return A set with the direct approvers of the given hash | ||
* @throws Exception | ||
*/ | ||
private HashSet<Hash> getTxDirectApproversHashes(Hash txHash, Map<Hash, HashSet<Hash>> txToDirectApprovers) | ||
private Set<Hash> getTxDirectApproversHashes(Hash txHash, Map<Hash, Set<Hash>> txToDirectApprovers) | ||
throws Exception { | ||
|
||
HashSet<Hash> txApprovers = txToDirectApprovers.get(txHash); | ||
Set<Hash> txApprovers = txToDirectApprovers.get(txHash); | ||
if (txApprovers == null) { | ||
ApproveeViewModel approvers = ApproveeViewModel.load(tangle, txHash); | ||
Collection<Hash> appHashes = CollectionUtils.emptyIfNull(approvers.getHashes()); | ||
Collection<Hash> appHashes; | ||
if (approvers == null || approvers.getHashes() == null) { | ||
appHashes = Collections.emptySet(); | ||
} else { | ||
appHashes = approvers.getHashes(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is cleaner to write it this way:
Only change if you agree, you don't have to. I care less about that. It is just less lines. |
||
|
||
txApprovers = new HashSet<>(appHashes.size()); | ||
for (Hash appHash : appHashes) { | ||
// if not genesis (the tx that confirms itself) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -283,7 +283,6 @@ public void testTangleWithCircle2() throws Exception { | |
} | ||
|
||
@Test | ||
@Ignore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we using the prefix again? When I asked before I just didn't check what this unit test does. |
||
public void testCollsionsInDiamondTangle() throws Exception { | ||
TransactionViewModel transaction, transaction1, transaction2, transaction3; | ||
transaction = new TransactionViewModel(getTransactionTrits(), getTransactionHash()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give a better description of the algorithm?
Try not to refer to the other implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe delete the other implementation, then you can call this one Cumulative Weight Calculator. Then we won't have to maintain more code. Also it will make you improve the javadoc (you can define CW in the doc)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should have copied the description but not the Link!!
The link explains the old algo which you deleted
Simply write exactly the following:
"Calculates the cumulative weight for each transaction above a certain entry point. Cumulative weight is an integer defined as the number of approving transactions plus one. We calculate it by doing a graph traversal from each transaction above a certain entry point and counting the number of different transactions we pass."