Add optional parameter to sample and sampleSize
This commit is contained in:
@@ -118,7 +118,10 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
const fromStatus =
|
||||
fromPoolId === undefined || stakingPools[fromPoolId].lastFinalized.isLessThan(currentEpoch.minus(1))
|
||||
? StakeStatus.Undelegated
|
||||
: (Pseudorandom.sample([StakeStatus.Undelegated, StakeStatus.Delegated]) as StakeStatus);
|
||||
: (Pseudorandom.sample(
|
||||
[StakeStatus.Undelegated, StakeStatus.Delegated],
|
||||
[0.2, 0.8],
|
||||
) as StakeStatus);
|
||||
const from = new StakeInfo(fromStatus, fromPoolId);
|
||||
|
||||
// Pick a random pool to move the stake to
|
||||
@@ -128,7 +131,10 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
const toStatus =
|
||||
toPoolId === undefined || stakingPools[toPoolId].lastFinalized.isLessThan(currentEpoch.minus(1))
|
||||
? StakeStatus.Undelegated
|
||||
: (Pseudorandom.sample([StakeStatus.Undelegated, StakeStatus.Delegated]) as StakeStatus);
|
||||
: (Pseudorandom.sample(
|
||||
[StakeStatus.Undelegated, StakeStatus.Delegated],
|
||||
[0.2, 0.8],
|
||||
) as StakeStatus);
|
||||
const to = new StakeInfo(toStatus, toPoolId);
|
||||
|
||||
// The next epoch balance of the `from` stake is the amount that can be moved
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Numberish } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
import * as seedrandom from 'seedrandom';
|
||||
|
||||
class PRNGWrapper {
|
||||
@@ -10,11 +11,19 @@ class PRNGWrapper {
|
||||
* Pseudorandom version of _.sample. Picks an element of the given array with uniform probability.
|
||||
* Return undefined if the array is empty.
|
||||
*/
|
||||
public sample<T>(arr: T[]): T | undefined {
|
||||
public sample<T>(arr: T[], weights?: number[]): T | undefined {
|
||||
if (arr.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
const index = Math.abs(this.rng.int32()) % arr.length;
|
||||
|
||||
let index: number;
|
||||
if (weights !== undefined) {
|
||||
const cdf = weights.map((_weight, i) => _.sum(weights.slice(0, i + 1)) / _.sum(weights));
|
||||
const x = this.rng();
|
||||
index = cdf.findIndex(value => value > x);
|
||||
} else {
|
||||
index = Math.abs(this.rng.int32()) % arr.length;
|
||||
}
|
||||
return arr[index];
|
||||
}
|
||||
|
||||
@@ -22,13 +31,13 @@ class PRNGWrapper {
|
||||
* Pseudorandom version of _.sampleSize. Returns an array of `n` samples from the given array
|
||||
* (with replacement), chosen with uniform probability. Return undefined if the array is empty.
|
||||
*/
|
||||
public sampleSize<T>(arr: T[], n: number): T[] | undefined {
|
||||
public sampleSize<T>(arr: T[], n: number, weights?: number[]): T[] | undefined {
|
||||
if (arr.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
const samples = [];
|
||||
for (let i = 0; i < n; i++) {
|
||||
samples.push(this.sample(arr) as T);
|
||||
samples.push(this.sample(arr, weights) as T);
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { blockchainTests } from '@0x/contracts-test-utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import { PoolOperator } from '../framework/actors/pool_operator';
|
||||
@@ -14,12 +15,12 @@ export class PoolManagementSimulation extends Simulation {
|
||||
const { actors } = this.environment;
|
||||
const operators = filterActorsByRole(actors, PoolOperator);
|
||||
|
||||
const actions = [
|
||||
...operators.map(operator => operator.simulationActions.validCreateStakingPool),
|
||||
...operators.map(operator => operator.simulationActions.validDecreaseStakingPoolOperatorShare),
|
||||
];
|
||||
const [actions, weights] = _.unzip([
|
||||
...operators.map(operator => [operator.simulationActions.validCreateStakingPool, 0.4]),
|
||||
...operators.map(operator => [operator.simulationActions.validDecreaseStakingPoolOperatorShare, 0.6]),
|
||||
]) as [AsyncIterableIterator<AssertionResult | void>[], number[]];
|
||||
while (true) {
|
||||
const action = Pseudorandom.sample(actions);
|
||||
const action = Pseudorandom.sample(actions, weights);
|
||||
yield (await action!.next()).value; // tslint:disable-line:no-non-null-assertion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { blockchainTests } from '@0x/contracts-test-utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import { MakerTaker } from '../framework/actors/hybrids';
|
||||
@@ -22,14 +23,14 @@ export class PoolMembershipSimulation extends Simulation {
|
||||
|
||||
const poolManagement = new PoolManagementSimulation(this.environment);
|
||||
|
||||
const actions = [
|
||||
...makers.map(maker => maker.simulationActions.validJoinStakingPool),
|
||||
...takers.map(taker => taker.simulationActions.validFillOrder),
|
||||
poolManagement.generator,
|
||||
];
|
||||
const [actions, weights] = _.unzip([
|
||||
...makers.map(maker => [maker.simulationActions.validJoinStakingPool, 0.2 / makers.length]),
|
||||
...takers.map(taker => [taker.simulationActions.validFillOrder, 0.6 / takers.length]),
|
||||
[poolManagement.generator, 0.2],
|
||||
]) as [AsyncIterableIterator<AssertionResult | void>[], number[]];
|
||||
|
||||
while (true) {
|
||||
const action = Pseudorandom.sample(actions);
|
||||
const action = Pseudorandom.sample(actions, weights);
|
||||
yield (await action!.next()).value; // tslint:disable-line:no-non-null-assertion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { blockchainTests } from '@0x/contracts-test-utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import { StakerOperator } from '../framework/actors/hybrids';
|
||||
@@ -20,14 +21,15 @@ export class StakeManagementSimulation extends Simulation {
|
||||
|
||||
const poolManagement = new PoolManagementSimulation(this.environment);
|
||||
|
||||
const actions = [
|
||||
...stakers.map(staker => staker.simulationActions.validStake),
|
||||
...stakers.map(staker => staker.simulationActions.validUnstake),
|
||||
...stakers.map(staker => staker.simulationActions.validMoveStake),
|
||||
poolManagement.generator,
|
||||
];
|
||||
const [actions, weights] = _.unzip([
|
||||
...stakers.map(staker => [staker.simulationActions.validStake, 0.3]),
|
||||
...stakers.map(staker => [staker.simulationActions.validUnstake, 0.2]),
|
||||
...stakers.map(staker => [staker.simulationActions.validMoveStake, 0.3]),
|
||||
[poolManagement.generator, 0.2],
|
||||
]) as [AsyncIterableIterator<AssertionResult | void>[], number[]];
|
||||
|
||||
while (true) {
|
||||
const action = Pseudorandom.sample(actions);
|
||||
const action = Pseudorandom.sample(actions, weights);
|
||||
yield (await action!.next()).value; // tslint:disable-line:no-non-null-assertion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { blockchainTests } from '@0x/contracts-test-utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import {
|
||||
@@ -32,15 +33,15 @@ export class StakingRewardsSimulation extends Simulation {
|
||||
const poolMembership = new PoolMembershipSimulation(this.environment);
|
||||
const stakeManagement = new StakeManagementSimulation(this.environment);
|
||||
|
||||
const actions = [
|
||||
...stakers.map(staker => staker.simulationActions.validWithdrawDelegatorRewards),
|
||||
...keepers.map(keeper => keeper.simulationActions.validFinalizePool),
|
||||
...keepers.map(keeper => keeper.simulationActions.validEndEpoch),
|
||||
poolMembership.generator,
|
||||
stakeManagement.generator,
|
||||
];
|
||||
const [actions, weights] = _.unzip([
|
||||
...stakers.map(staker => [staker.simulationActions.validWithdrawDelegatorRewards, 0.1 / stakers.length]),
|
||||
...keepers.map(keeper => [keeper.simulationActions.validFinalizePool, 0.1 / keepers.length]),
|
||||
...keepers.map(keeper => [keeper.simulationActions.validEndEpoch, 0.1 / keepers.length]),
|
||||
[poolMembership.generator, 0.5],
|
||||
[stakeManagement.generator, 0.2],
|
||||
]) as [AsyncIterableIterator<AssertionResult | void>[], number[]];
|
||||
while (true) {
|
||||
const action = Pseudorandom.sample(actions);
|
||||
const action = Pseudorandom.sample(actions, weights);
|
||||
yield (await action!.next()).value; // tslint:disable-line:no-non-null-assertion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +83,10 @@ export function loadCurrentBalance(balance: StoredBalance, epoch: BigNumber): St
|
||||
* Simulates _increaseNextBalance
|
||||
*/
|
||||
export function increaseNextBalance(balance: StoredBalance, amount: Numberish, epoch: BigNumber): StoredBalance {
|
||||
const newBalance = loadCurrentBalance(balance, epoch);
|
||||
return {
|
||||
...loadCurrentBalance(balance, epoch),
|
||||
nextEpochBalance: balance.nextEpochBalance.plus(amount),
|
||||
...newBalance,
|
||||
nextEpochBalance: newBalance.nextEpochBalance.plus(amount),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -93,9 +94,10 @@ export function increaseNextBalance(balance: StoredBalance, amount: Numberish, e
|
||||
* Simulates _decreaseNextBalance
|
||||
*/
|
||||
export function decreaseNextBalance(balance: StoredBalance, amount: Numberish, epoch: BigNumber): StoredBalance {
|
||||
const newBalance = loadCurrentBalance(balance, epoch);
|
||||
return {
|
||||
...loadCurrentBalance(balance, epoch),
|
||||
nextEpochBalance: balance.nextEpochBalance.minus(amount),
|
||||
...newBalance,
|
||||
nextEpochBalance: newBalance.nextEpochBalance.minus(amount),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -107,10 +109,11 @@ export function increaseCurrentAndNextBalance(
|
||||
amount: Numberish,
|
||||
epoch: BigNumber,
|
||||
): StoredBalance {
|
||||
const newBalance = loadCurrentBalance(balance, epoch);
|
||||
return {
|
||||
...loadCurrentBalance(balance, epoch),
|
||||
currentEpochBalance: balance.currentEpochBalance.plus(amount),
|
||||
nextEpochBalance: balance.nextEpochBalance.plus(amount),
|
||||
...newBalance,
|
||||
currentEpochBalance: newBalance.currentEpochBalance.plus(amount),
|
||||
nextEpochBalance: newBalance.nextEpochBalance.plus(amount),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -122,10 +125,11 @@ export function decreaseCurrentAndNextBalance(
|
||||
amount: Numberish,
|
||||
epoch: BigNumber,
|
||||
): StoredBalance {
|
||||
const newBalance = loadCurrentBalance(balance, epoch);
|
||||
return {
|
||||
...loadCurrentBalance(balance, epoch),
|
||||
currentEpochBalance: balance.currentEpochBalance.minus(amount),
|
||||
nextEpochBalance: balance.nextEpochBalance.minus(amount),
|
||||
...newBalance,
|
||||
currentEpochBalance: newBalance.currentEpochBalance.minus(amount),
|
||||
nextEpochBalance: newBalance.nextEpochBalance.minus(amount),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user