Best Python code snippet using pytest-benchmark
pbkdf2.py
Source:pbkdf2.py
1"""passlib.handlers.pbkdf - PBKDF2 based hashes"""2#=============================================================================3# imports4#=============================================================================5# core6from binascii import hexlify, unhexlify7from base64 import b64encode, b64decode8import logging; log = logging.getLogger(__name__)9# site10# pkg11from passlib.utils import to_unicode12from passlib.utils.binary import ab64_decode, ab64_encode13from passlib.utils.compat import str_to_bascii, u, uascii_to_str, unicode14from passlib.crypto.digest import pbkdf2_hmac15import passlib.utils.handlers as uh16# local17__all__ = [18 "pbkdf2_sha1",19 "pbkdf2_sha256",20 "pbkdf2_sha512",21 "cta_pbkdf2_sha1",22 "dlitz_pbkdf2_sha1",23 "grub_pbkdf2_sha512",24]25#=============================================================================26#27#=============================================================================28class Pbkdf2DigestHandler(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):29 """base class for various pbkdf2_{digest} algorithms"""30 #===================================================================31 # class attrs32 #===================================================================33 #--GenericHandler--34 setting_kwds = ("salt", "salt_size", "rounds")35 checksum_chars = uh.HASH64_CHARS36 #--HasSalt--37 default_salt_size = 1638 max_salt_size = 102439 #--HasRounds--40 default_rounds = None # set by subclass41 min_rounds = 142 max_rounds = 0xffffffff # setting at 32-bit limit for now43 rounds_cost = "linear"44 #--this class--45 _digest = None # name of subclass-specified hash46 # NOTE: max_salt_size and max_rounds are arbitrarily chosen to provide sanity check.47 # the underlying pbkdf2 specifies no bounds for either.48 # NOTE: defaults chosen to be at least as large as pbkdf2 rfc recommends...49 # >8 bytes of entropy in salt, >1000 rounds50 # increased due to time since rfc established51 #===================================================================52 # methods53 #===================================================================54 @classmethod55 def from_string(cls, hash):56 rounds, salt, chk = uh.parse_mc3(hash, cls.ident, handler=cls)57 salt = ab64_decode(salt.encode("ascii"))58 if chk:59 chk = ab64_decode(chk.encode("ascii"))60 return cls(rounds=rounds, salt=salt, checksum=chk)61 def to_string(self):62 salt = ab64_encode(self.salt).decode("ascii")63 chk = ab64_encode(self.checksum).decode("ascii")64 return uh.render_mc3(self.ident, self.rounds, salt, chk)65 def _calc_checksum(self, secret):66 # NOTE: pbkdf2_hmac() will encode secret & salt using UTF867 return pbkdf2_hmac(self._digest, secret, self.salt, self.rounds, self.checksum_size)68def create_pbkdf2_hash(hash_name, digest_size, rounds=12000, ident=None, module=__name__):69 """create new Pbkdf2DigestHandler subclass for a specific hash"""70 name = 'pbkdf2_' + hash_name71 if ident is None:72 ident = u("$pbkdf2-%s$") % (hash_name,)73 base = Pbkdf2DigestHandler74 return type(name, (base,), dict(75 __module__=module, # so ABCMeta won't clobber it.76 name=name,77 ident=ident,78 _digest = hash_name,79 default_rounds=rounds,80 checksum_size=digest_size,81 encoded_checksum_size=(digest_size*4+2)//3,82 __doc__="""This class implements a generic ``PBKDF2-HMAC-%(digest)s``-based password hash, and follows the :ref:`password-hash-api`.83 It supports a variable-length salt, and a variable number of rounds.84 The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:85 :type salt: bytes86 :param salt:87 Optional salt bytes.88 If specified, the length must be between 0-1024 bytes.89 If not specified, a %(dsc)d byte salt will be autogenerated (this is recommended).90 :type salt_size: int91 :param salt_size:92 Optional number of bytes to use when autogenerating new salts.93 Defaults to %(dsc)d bytes, but can be any value between 0 and 1024.94 :type rounds: int95 :param rounds:96 Optional number of rounds to use.97 Defaults to %(dr)d, but must be within ``range(1,1<<32)``.98 :type relaxed: bool99 :param relaxed:100 By default, providing an invalid value for one of the other101 keywords will result in a :exc:`ValueError`. If ``relaxed=True``,102 and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`103 will be issued instead. Correctable errors include ``rounds``104 that are too small or too large, and ``salt`` strings that are too long.105 .. versionadded:: 1.6106 """ % dict(digest=hash_name.upper(), dsc=base.default_salt_size, dr=rounds)107 ))108#------------------------------------------------------------------------109# derived handlers110#------------------------------------------------------------------------111pbkdf2_sha1 = create_pbkdf2_hash("sha1", 20, 131000, ident=u("$pbkdf2$"))112pbkdf2_sha256 = create_pbkdf2_hash("sha256", 32, 29000)113pbkdf2_sha512 = create_pbkdf2_hash("sha512", 64, 25000)114ldap_pbkdf2_sha1 = uh.PrefixWrapper("ldap_pbkdf2_sha1", pbkdf2_sha1, "{PBKDF2}", "$pbkdf2$", ident=True)115ldap_pbkdf2_sha256 = uh.PrefixWrapper("ldap_pbkdf2_sha256", pbkdf2_sha256, "{PBKDF2-SHA256}", "$pbkdf2-sha256$", ident=True)116ldap_pbkdf2_sha512 = uh.PrefixWrapper("ldap_pbkdf2_sha512", pbkdf2_sha512, "{PBKDF2-SHA512}", "$pbkdf2-sha512$", ident=True)117#=============================================================================118# cryptacular's pbkdf2 hash119#=============================================================================120# bytes used by cta hash for base64 values 63 & 64121CTA_ALTCHARS = b"-_"122class cta_pbkdf2_sha1(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):123 """This class implements Cryptacular's PBKDF2-based crypt algorithm, and follows the :ref:`password-hash-api`.124 It supports a variable-length salt, and a variable number of rounds.125 The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:126 :type salt: bytes127 :param salt:128 Optional salt bytes.129 If specified, it may be any length.130 If not specified, a one will be autogenerated (this is recommended).131 :type salt_size: int132 :param salt_size:133 Optional number of bytes to use when autogenerating new salts.134 Defaults to 16 bytes, but can be any value between 0 and 1024.135 :type rounds: int136 :param rounds:137 Optional number of rounds to use.138 Defaults to 60000, must be within ``range(1,1<<32)``.139 :type relaxed: bool140 :param relaxed:141 By default, providing an invalid value for one of the other142 keywords will result in a :exc:`ValueError`. If ``relaxed=True``,143 and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`144 will be issued instead. Correctable errors include ``rounds``145 that are too small or too large, and ``salt`` strings that are too long.146 .. versionadded:: 1.6147 """148 #===================================================================149 # class attrs150 #===================================================================151 #--GenericHandler--152 name = "cta_pbkdf2_sha1"153 setting_kwds = ("salt", "salt_size", "rounds")154 ident = u("$p5k2$")155 checksum_size = 20156 # NOTE: max_salt_size and max_rounds are arbitrarily chosen to provide a157 # sanity check. underlying algorithm (and reference implementation)158 # allows effectively unbounded values for both of these parameters.159 #--HasSalt--160 default_salt_size = 16161 max_salt_size = 1024162 #--HasRounds--163 default_rounds = pbkdf2_sha1.default_rounds164 min_rounds = 1165 max_rounds = 0xffffffff # setting at 32-bit limit for now166 rounds_cost = "linear"167 #===================================================================168 # formatting169 #===================================================================170 # hash $p5k2$1000$ZxK4ZBJCfQg=$jJZVscWtO--p1-xIZl6jhO2LKR0=171 # ident $p5k2$172 # rounds 1000173 # salt ZxK4ZBJCfQg=174 # chk jJZVscWtO--p1-xIZl6jhO2LKR0=175 # NOTE: rounds in hex176 @classmethod177 def from_string(cls, hash):178 # NOTE: passlib deviation - forbidding zero-padded rounds179 rounds, salt, chk = uh.parse_mc3(hash, cls.ident, rounds_base=16, handler=cls)180 salt = b64decode(salt.encode("ascii"), CTA_ALTCHARS)181 if chk:182 chk = b64decode(chk.encode("ascii"), CTA_ALTCHARS)183 return cls(rounds=rounds, salt=salt, checksum=chk)184 def to_string(self):185 salt = b64encode(self.salt, CTA_ALTCHARS).decode("ascii")186 chk = b64encode(self.checksum, CTA_ALTCHARS).decode("ascii")187 return uh.render_mc3(self.ident, self.rounds, salt, chk, rounds_base=16)188 #===================================================================189 # backend190 #===================================================================191 def _calc_checksum(self, secret):192 # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8193 return pbkdf2_hmac("sha1", secret, self.salt, self.rounds, 20)194 #===================================================================195 # eoc196 #===================================================================197#=============================================================================198# dlitz's pbkdf2 hash199#=============================================================================200class dlitz_pbkdf2_sha1(uh.HasRounds, uh.HasSalt, uh.GenericHandler):201 """This class implements Dwayne Litzenberger's PBKDF2-based crypt algorithm, and follows the :ref:`password-hash-api`.202 It supports a variable-length salt, and a variable number of rounds.203 The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:204 :type salt: str205 :param salt:206 Optional salt string.207 If specified, it may be any length, but must use the characters in the regexp range ``[./0-9A-Za-z]``.208 If not specified, a 16 character salt will be autogenerated (this is recommended).209 :type salt_size: int210 :param salt_size:211 Optional number of bytes to use when autogenerating new salts.212 Defaults to 16 bytes, but can be any value between 0 and 1024.213 :type rounds: int214 :param rounds:215 Optional number of rounds to use.216 Defaults to 60000, must be within ``range(1,1<<32)``.217 :type relaxed: bool218 :param relaxed:219 By default, providing an invalid value for one of the other220 keywords will result in a :exc:`ValueError`. If ``relaxed=True``,221 and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`222 will be issued instead. Correctable errors include ``rounds``223 that are too small or too large, and ``salt`` strings that are too long.224 .. versionadded:: 1.6225 """226 #===================================================================227 # class attrs228 #===================================================================229 #--GenericHandler--230 name = "dlitz_pbkdf2_sha1"231 setting_kwds = ("salt", "salt_size", "rounds")232 ident = u("$p5k2$")233 _stub_checksum = u("0" * 48 + "=")234 # NOTE: max_salt_size and max_rounds are arbitrarily chosen to provide a235 # sanity check. underlying algorithm (and reference implementation)236 # allows effectively unbounded values for both of these parameters.237 #--HasSalt--238 default_salt_size = 16239 max_salt_size = 1024240 salt_chars = uh.HASH64_CHARS241 #--HasRounds--242 # NOTE: for security, the default here is set to match pbkdf2_sha1,243 # even though this hash's extra block makes it twice as slow.244 default_rounds = pbkdf2_sha1.default_rounds245 min_rounds = 1246 max_rounds = 0xffffffff # setting at 32-bit limit for now247 rounds_cost = "linear"248 #===================================================================249 # formatting250 #===================================================================251 # hash $p5k2$c$u9HvcT4d$Sd1gwSVCLZYAuqZ25piRnbBEoAesaa/g252 # ident $p5k2$253 # rounds c254 # salt u9HvcT4d255 # chk Sd1gwSVCLZYAuqZ25piRnbBEoAesaa/g256 # rounds in lowercase hex, no zero padding257 @classmethod258 def from_string(cls, hash):259 rounds, salt, chk = uh.parse_mc3(hash, cls.ident, rounds_base=16,260 default_rounds=400, handler=cls)261 return cls(rounds=rounds, salt=salt, checksum=chk)262 def to_string(self):263 rounds = self.rounds264 if rounds == 400:265 rounds = None # omit rounds measurement if == 400266 return uh.render_mc3(self.ident, rounds, self.salt, self.checksum, rounds_base=16)267 def _get_config(self):268 rounds = self.rounds269 if rounds == 400:270 rounds = None # omit rounds measurement if == 400271 return uh.render_mc3(self.ident, rounds, self.salt, None, rounds_base=16)272 #===================================================================273 # backend274 #===================================================================275 def _calc_checksum(self, secret):276 # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8277 salt = self._get_config()278 result = pbkdf2_hmac("sha1", secret, salt, self.rounds, 24)279 return ab64_encode(result).decode("ascii")280 #===================================================================281 # eoc282 #===================================================================283#=============================================================================284# crowd285#=============================================================================286class atlassian_pbkdf2_sha1(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):287 """This class implements the PBKDF2 hash used by Atlassian.288 It supports a fixed-length salt, and a fixed number of rounds.289 The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:290 :type salt: bytes291 :param salt:292 Optional salt bytes.293 If specified, the length must be exactly 16 bytes.294 If not specified, a salt will be autogenerated (this is recommended).295 :type relaxed: bool296 :param relaxed:297 By default, providing an invalid value for one of the other298 keywords will result in a :exc:`ValueError`. If ``relaxed=True``,299 and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`300 will be issued instead. Correctable errors include301 ``salt`` strings that are too long.302 .. versionadded:: 1.6303 """304 #--GenericHandler--305 name = "atlassian_pbkdf2_sha1"306 setting_kwds =("salt",)307 ident = u("{PKCS5S2}")308 checksum_size = 32309 #--HasRawSalt--310 min_salt_size = max_salt_size = 16311 @classmethod312 def from_string(cls, hash):313 hash = to_unicode(hash, "ascii", "hash")314 ident = cls.ident315 if not hash.startswith(ident):316 raise uh.exc.InvalidHashError(cls)317 data = b64decode(hash[len(ident):].encode("ascii"))318 salt, chk = data[:16], data[16:]319 return cls(salt=salt, checksum=chk)320 def to_string(self):321 data = self.salt + self.checksum322 hash = self.ident + b64encode(data).decode("ascii")323 return uascii_to_str(hash)324 def _calc_checksum(self, secret):325 # TODO: find out what crowd's policy is re: unicode326 # crowd seems to use a fixed number of rounds.327 # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8328 return pbkdf2_hmac("sha1", secret, self.salt, 10000, 32)329#=============================================================================330# grub331#=============================================================================332class grub_pbkdf2_sha512(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):333 """This class implements Grub's pbkdf2-hmac-sha512 hash, and follows the :ref:`password-hash-api`.334 It supports a variable-length salt, and a variable number of rounds.335 The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:336 :type salt: bytes337 :param salt:338 Optional salt bytes.339 If specified, the length must be between 0-1024 bytes.340 If not specified, a 64 byte salt will be autogenerated (this is recommended).341 :type salt_size: int342 :param salt_size:343 Optional number of bytes to use when autogenerating new salts.344 Defaults to 64 bytes, but can be any value between 0 and 1024.345 :type rounds: int346 :param rounds:347 Optional number of rounds to use.348 Defaults to 19000, but must be within ``range(1,1<<32)``.349 :type relaxed: bool350 :param relaxed:351 By default, providing an invalid value for one of the other352 keywords will result in a :exc:`ValueError`. If ``relaxed=True``,353 and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`354 will be issued instead. Correctable errors include ``rounds``355 that are too small or too large, and ``salt`` strings that are too long.356 .. versionadded:: 1.6357 """358 name = "grub_pbkdf2_sha512"359 setting_kwds = ("salt", "salt_size", "rounds")360 ident = u("grub.pbkdf2.sha512.")361 checksum_size = 64362 # NOTE: max_salt_size and max_rounds are arbitrarily chosen to provide a363 # sanity check. the underlying pbkdf2 specifies no bounds for either,364 # and it's not clear what grub specifies.365 default_salt_size = 64366 max_salt_size = 1024367 default_rounds = pbkdf2_sha512.default_rounds368 min_rounds = 1369 max_rounds = 0xffffffff # setting at 32-bit limit for now370 rounds_cost = "linear"371 @classmethod372 def from_string(cls, hash):373 rounds, salt, chk = uh.parse_mc3(hash, cls.ident, sep=u("."),374 handler=cls)375 salt = unhexlify(salt.encode("ascii"))376 if chk:377 chk = unhexlify(chk.encode("ascii"))378 return cls(rounds=rounds, salt=salt, checksum=chk)379 def to_string(self):380 salt = hexlify(self.salt).decode("ascii").upper()381 chk = hexlify(self.checksum).decode("ascii").upper()382 return uh.render_mc3(self.ident, self.rounds, salt, chk, sep=u("."))383 def _calc_checksum(self, secret):384 # TODO: find out what grub's policy is re: unicode385 # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8386 return pbkdf2_hmac("sha512", secret, self.salt, self.rounds, 64)387#=============================================================================388# eof...
kellycoinflip.py
Source:kellycoinflip.py
1import gym2from gym import spaces3from gym.utils import seeding4from gym.spaces import prng5# for Generalized Kelly coinflip game distributions:6from scipy.stats import genpareto7import numpy as np8import numpy.random9def flip(edge, np_random):10 return np_random.uniform() < edge11class KellyCoinflipEnv(gym.Env):12 """The Kelly coinflip game is a simple gambling introduced by Haghani & Dewey 2016's 'Rational Decision-Making Under Uncertainty: Observed Betting Patterns on a Biased Coin' (https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2856963), to test human decision-making in a setting like that of the stock market: positive expected value but highly stochastic; they found many subjects performed badly, often going broke, even though optimal play would reach the maximum with ~95% probability. In the coinflip game, the player starts with $25.00 to gamble over 300 rounds; each round, they can bet anywhere up to their net worth (in penny increments), and then a coin is flipped; with P=0.6, the player wins twice what they bet, otherwise, they lose it. $250 is the maximum players are allowed to have. At the end of the 300 rounds, they keep whatever they have. The human subjects earned an average of $91; a simple use of the Kelly criterion (https://en.wikipedia.org/wiki/Kelly_criterion), giving a strategy of betting 20% until the cap is hit, would earn $240; a decision tree analysis shows that optimal play earns $246 (https://www.gwern.net/Coin-flip). The game short-circuits when either wealth = $0 (since one can never recover) or wealth = cap (trivial optimal play: one simply bets nothing thereafter). In this implementation, we default to the paper settings of $25, 60% odds, wealth cap of $250, and 300 rounds. To specify the action space in advance, we multiply the wealth cap (in dollars) by 100 (to allow for all penny bets); should one attempt to bet more money than one has, it is rounded down to one's net worth. (Alternately, a mistaken bet could end the episode immediately; it's not clear to me which version would be better.) For a harder version which randomizes the 3 key parameters, see the Generalized Kelly coinflip game."""13 metadata = {'render.modes': ['human']}14 def __init__(self, initialWealth=25, edge=0.6, maxWealth=250, maxRounds=300):15 self.action_space = spaces.Discrete(maxWealth*100) # betting in penny increments16 self.observation_space = spaces.Tuple((17 spaces.Box(0, maxWealth, [1]), # (w,b)18 spaces.Discrete(maxRounds+1)))19 self.reward_range = (0, maxWealth)20 self.edge = edge21 self.wealth = initialWealth22 self.initialWealth = initialWealth23 self.maxRounds = maxRounds24 self.maxWealth = maxWealth25 self._seed()26 self._reset()27 def _seed(self, seed=None):28 self.np_random, seed = seeding.np_random(seed)29 return [seed]30 def _step(self, action):31 action = action/100 # convert from pennies to dollars32 if action > self.wealth: # treat attempts to bet more than possess as == betting everything33 action = self.wealth34 if self.wealth <= 0:35 done = True36 reward = 037 else:38 if self.rounds == 0:39 done = True40 reward = self.wealth41 else:42 self.rounds = self.rounds - 143 done = False44 reward = 045 coinflip = flip(self.edge, self.np_random)46 if coinflip:47 self.wealth = min(self.maxWealth, self.wealth + action)48 else:49 self.wealth = self.wealth - action50 return self._get_obs(), reward, done, {}51 def _get_obs(self):52 return (np.array([self.wealth]), self.rounds)53 def _reset(self):54 self.rounds = self.maxRounds55 self.wealth = self.initialWealth56 return self._get_obs()57 def _render(self, mode='human', close=True):58 if close: return59 print("Current wealth: ", self.wealth, "; Rounds left: ", self.rounds)60class KellyCoinflipGeneralizedEnv(gym.Env):61 """The Generalized Kelly coinflip game is an extension by ArthurB & Gwern Branwen which expands the Kelly coinflip game MDP into a POMDP, where the 3 key parameters (edge, maximum wealth, and number of rounds) are unknown random variables drawn from 3 distributions: a Beta(7,3) for the coinflip edge 0-1, a N(300,25) the total number of rounds, and a Pareto(5,200) for the wealth cap. These distributions are chosen to be conjugate & easily updatable, to allow for inference (other choices like the geometric for number of rounds wouldn't make observations informative), and to loosely reflect what a human might expect in the original Kelly coinflip game given that the number of rounds wasn't strictly fixed and they weren't told the wealth cap until they neared it. With these particular distributions, the entire history of the game can be summarized into a few sufficient statistics of rounds-elapsed/wins/losses/max-wealth-ever-reached, from which the Bayes-optimal decision can (in theory) be made; to avoid all agents having to tediously track those sufficient statistics manually in the same way, the observation space is augmented from wealth/rounds-left (rounds-left is deleted because it is a hidden variable) to current-wealth/rounds-elapsed/wins/losses/maximum-observed-wealth. The simple Kelly coinflip game can easily be solved by calculating decision trees, but the Generalized Kelly coinflip game may be intractable (although the analysis for the edge case alone suggests that the Bayes-optimal value may be very close to what one would calculate using a decision tree for any specific case), and represents a good challenge for RL agents."""62 metadata = {'render.modes': ['human']}63 def __init__(self, initialWealth=25, edgePriorAlpha=7, edgePriorBeta=3, maxWealthAlpha=5, maxWealthM=200, maxRoundsMean=300, maxRoundsSD=25, reseed=True):64 # store the hyperparameters for passing back into __init__() during resets so the same hyperparameters govern the next game's parameters, as the user expects: TODO: this is boilerplate, is there any more elegant way to do this?65 self.initialWealth=initialWealth66 self.edgePriorAlpha=edgePriorAlpha67 self.edgePriorBeta=edgePriorBeta68 self.maxWealthAlpha=maxWealthAlpha69 self.maxWealthM=maxWealthM70 self.maxRoundsMean=maxRoundsMean71 self.maxRoundsSD=maxRoundsSD72 # draw this game's set of parameters:73 edge = prng.np_random.beta(edgePriorAlpha, edgePriorBeta)74 maxWealth = round(genpareto.rvs(maxWealthAlpha, maxWealthM, random_state=prng.np_random))75 maxRounds = round(prng.np_random.normal(maxRoundsMean, maxRoundsSD))76 # add an additional global variable which is the sufficient statistic for the Pareto distribution on wealth cap;77 # alpha doesn't update, but x_m does, and simply is the highest wealth count we've seen to date:78 self.maxEverWealth = initialWealth79 # for the coinflip edge, it is total wins/losses:80 self.wins = 081 self.losses = 082 # for the number of rounds, we need to remember how many rounds we've played:83 self.roundsElapsed = 084 # the rest proceeds as before:85 self.action_space = spaces.Discrete(maxWealth*100)86 self.observation_space = spaces.Tuple((87 spaces.Box(0, maxWealth, shape=[1]), # current wealth88 spaces.Discrete(maxRounds+1), # rounds elapsed89 spaces.Discrete(maxRounds+1), # wins90 spaces.Discrete(maxRounds+1), # losses91 spaces.Box(0, maxWealth, [1]))) # maximum observed wealth92 self.reward_range = (0, maxWealth)93 self.edge = edge94 self.wealth = initialWealth95 self.initialWealth = initialWealth96 self.maxRounds = maxRounds97 self.rounds = self.maxRounds98 self.maxWealth = maxWealth99 if reseed or not hasattr(self, 'np_random') : self._seed()100 def _seed(self, seed=None):101 self.np_random, seed = seeding.np_random(seed)102 return [seed]103 def _step(self, action):104 action = action/100105 if action > self.wealth:106 action = self.wealth107 if self.wealth <= 0:108 done = True109 reward = 0110 else:111 if self.rounds == 0:112 done = True113 reward = self.wealth114 else:115 self.rounds = self.rounds - 1116 done = False117 reward = 0118 coinflip = flip(self.edge, self.np_random)119 self.roundsElapsed = self.roundsElapsed+1120 if coinflip:121 self.wealth = min(self.maxWealth, self.wealth + action)122 self.maxEverWealth = max(self.wealth, self.maxEverWealth)123 self.wins = self.wins+1124 else:125 self.wealth = self.wealth - action126 self.losses = self.losses+1127 return self._get_obs(), reward, done, {}128 def _get_obs(self):129 return (np.array([self.wealth]), self.roundsElapsed, self.wins, self.losses, np.array([self.maxEverWealth]))130 def _reset(self):131 # re-init everything to draw new parameters etc, but preserve the RNG for reproducibility and pass in the same hyperparameters as originally specified:132 self.__init__(initialWealth=self.initialWealth, edgePriorAlpha=self.edgePriorAlpha, edgePriorBeta=self.edgePriorBeta, maxWealthAlpha=self.maxWealthAlpha, maxWealthM=self.maxWealthM, maxRoundsMean=self.maxRoundsMean, maxRoundsSD=self.maxRoundsSD, reseed=False)133 return self._get_obs()134 def _render(self, mode='human', close=True):135 if close: return136 print("Current wealth: ", self.wealth, "; Rounds left: ", self.rounds, "; True edge: ", self.edge,137 "; True max wealth: ", self.maxWealth, "; True stopping time: ", self.maxRounds, "; Rounds left: ",...
tournament_model.py
Source:tournament_model.py
...18 self.time_control = time_control19 self.description = description20 self.id = ''21 def create_tournament(self):22 self.rounds_ids = self.generate_rounds()23 tournament_id = self.t_table.insert(24 {"name": self.name,25 "location": self.location,26 "date_start": self.date_start,27 "date_end": self.date_end,28 "num_of_rounds": self.num_of_rounds,29 "rounds": self.rounds_ids,30 "players": self.players,31 "time_control": self.time_control,32 "description": self.description33 })34 return self.t_table.update(35 {'id': tournament_id}, doc_ids=[tournament_id])[0]36 def save_tournament(self):37 if self.id == '':38 result = self.create_tournament()39 else:40 result = self.t_table.update(41 {"name": self.name,42 "location": self.location,43 "date_start": self.date_start,44 "date_end": self.date_end,45 "num_of_rounds": self.num_of_rounds,46 "rounds": self.rounds,47 "players": self.players,48 "time_control": self.time_control,49 "description": self.description,50 "id": self.id51 }, doc_ids=[self.id])[0]52 return result53 @staticmethod54 def get_tournament_from_id(id_num):55 tournament = Tournament()56 data = tournament.t_table.get(doc_id=int(id_num))57 tournament.name = data["name"]58 tournament.location = data["location"]59 tournament.date_start = data["date_start"]60 tournament.date_end = data["date_end"]61 tournament.num_of_rounds = data["num_of_rounds"]62 tournament.time_control = data["time_control"]63 tournament.description = data["description"]64 tournament.players = []65 tournament.rounds = []66 tournament.id = id_num67 for player_id in data["players"]:68 player = Player.get_player_from_id(player_id)69 tournament.players.append(player)70 for round_id in data["rounds"]:71 round_ = Round.get_round_from_id(round_id)72 tournament.rounds.append(round_)73 return tournament74 def generate_rounds(self):75 rounds_ids = []76 for i in range(self.num_of_rounds):77 r = Round()78 r.generate_matches()79 round_id = r.create_round(i+1)80 rounds_ids.append(round_id)81 return rounds_ids82 def add_player(self, player):83 self.players.append(player)84 def matches(self):85 matches = []86 for round_ in self.rounds:87 matches.extend(round_.matches)88 return matches...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!