pyactup 2.2.1__tar.gz → 2.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyactup
3
- Version: 2.2.1
3
+ Version: 2.2.3
4
4
  Summary: A lightweight Python implementation of a subset of the ACT-R cognitive architecture’s Declarative Memory
5
- Home-page: https://bitbucket.org/dfmorrison/pyactup/
5
+ Home-page: https://dfmorrison.github.io/pyactup-documentation/
6
6
  Author: Don Morrison
7
7
  Author-email: dfm2@cmu.edu
8
8
  Platform: any
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyactup
3
- Version: 2.2.1
3
+ Version: 2.2.3
4
4
  Summary: A lightweight Python implementation of a subset of the ACT-R cognitive architecture’s Declarative Memory
5
- Home-page: https://bitbucket.org/dfmorrison/pyactup/
5
+ Home-page: https://dfmorrison.github.io/pyactup-documentation/
6
6
  Author: Don Morrison
7
7
  Author-email: dfm2@cmu.edu
8
8
  Platform: any
@@ -1,3 +1,4 @@
1
1
  numpy
2
2
  pylru
3
3
  prettytable
4
+ packaging
@@ -37,7 +37,7 @@ may be strictly algorithmic, may interact with human subjects, or may be embedde
37
37
  sites.
38
38
  """
39
39
 
40
- __version__ = "2.2.1"
40
+ __version__ = "2.2.3"
41
41
 
42
42
  if "dev" in __version__:
43
43
  print("PyACTUp version", __version__)
@@ -135,6 +135,7 @@ class Memory(dict):
135
135
  self._fixed_noise_time = None
136
136
  self._temperature_param = 1 # will be reset below, but is needed for noise assignment
137
137
  self._noise = None
138
+ self._noise_distribution = None
138
139
  self._decay = None
139
140
  self._optimized_learning = None
140
141
  self._use_actr_similarity = False
@@ -295,18 +296,33 @@ class Memory(dict):
295
296
  assert not self._index and not self._slot_name_index
296
297
  self._indexed_attributes = indexed_attributes
297
298
 
299
+ @staticmethod
300
+ def is_real(x, name, non_negative=True, positive=False, none_allowed=True):
301
+ if none_allowed and x is None:
302
+ return
303
+ if (x is True or x is False
304
+ or (positive and x <= 0)
305
+ or (non_negative and x < 0)):
306
+ if positive:
307
+ mod = " positive"
308
+ elif non_negative:
309
+ mod = " non-negative"
310
+ else:
311
+ mod = ""
312
+ raise ValueError(f"The {name}, {x}, must be{' None or' if none_allowed else ''} a{mod} real number")
313
+
298
314
  @property
299
315
  def time(self):
300
316
  """This ``Memory``'s current time.
301
317
  Time in PyACTUp is a dimensionless quantity, the interpretation of which is at the
302
- discretion of the modeler.
318
+ discretion of the modeler. Attempting to set the ``time`` to anything but a real
319
+ number raises a :exc:`ValueError`.
303
320
  """
304
321
  return self._time
305
322
 
306
323
  @time.setter
307
324
  def time(self, value):
308
- if not isinstance(value, Real):
309
- raise ValueError(f"Time {value} is not a real number")
325
+ Memory.is_real(value, "time", False, False, False)
310
326
  self._time = value
311
327
  if value != self._time:
312
328
  self._clear_fixed_noise()
@@ -322,6 +338,7 @@ class Memory(dict):
322
338
  chunks were created or reinforced will result in infinite or complex valued
323
339
  base-level activations and raise an :exc:`Exception`.
324
340
  """
341
+ Memory.is_real(amount, "time increment", False)
325
342
  if amount is not None:
326
343
  self.time += amount
327
344
  return self._time
@@ -381,8 +398,9 @@ class Memory(dict):
381
398
 
382
399
  @noise.setter
383
400
  def noise(self, value):
384
- if value < 0:
385
- raise ValueError(f"The noise, {value}, must not be negative")
401
+ Memory.is_real(value, "noise")
402
+ if value is None:
403
+ value = 0
386
404
  if self._temperature_param is None:
387
405
  t = Memory._validate_temperature(None, value)
388
406
  if not t:
@@ -391,9 +409,34 @@ class Memory(dict):
391
409
  else:
392
410
  self._temperature = t
393
411
  if value != self._noise:
394
- self._noise = value
412
+ self._noise = float(value)
395
413
  self._clear_fixed_noise()
396
414
 
415
+ @property
416
+ def noise_distribution(self):
417
+ """ Provide an alternative distribution from which noise is sampled.
418
+ If ``None`` the default logistic distribution is used. Otherwise the value of this
419
+ attribute should be a callable that takes no arguments and returns a real number.
420
+ It will be called once each time activation noise is required and the value,
421
+ scaled as usual by the :attr:`noise` parameter, will be used as the activation
422
+ noise. A :exc:`ValueError` is raised if an attempt is made to set this attribute
423
+ to anything other than a callable or ``None``.
424
+
425
+ .. warning::
426
+ It is rarely appropriate to use ``noise_distribution``. The default logistic
427
+ distribution is almost always a more appropriate choice. The ability to change
428
+ the distribution is provided only for esoteric purposes, and care should be
429
+ exercised lest biologically implausible models result.
430
+ """
431
+ return self._noise_distribution
432
+
433
+ @noise_distribution.setter
434
+ def noise_distribution(self, value):
435
+ if value is None or callable(value):
436
+ self._noise_distribution = value
437
+ else:
438
+ raise ValueError(f"The provided noise_distribution, {value}, is neither Callable nor None")
439
+
397
440
  @property
398
441
  def decay(self):
399
442
  """Controls the rate at which activation for chunks in memory decay with the passage of time.
@@ -411,12 +454,13 @@ class Memory(dict):
411
454
 
412
455
  @decay.setter
413
456
  def decay(self, value):
457
+ Memory.is_real(value, "decay")
414
458
  if value is not None:
415
- if value < 0:
416
- raise ValueError(f"The decay, {value}, must not be negative")
417
459
  if value >= 1 and self._optimized_learning is not None:
418
460
  raise ValueError(f"The decay, {value}, must be less than one if optimized_learning is used")
419
- self._decay = value
461
+ self._decay = float(value)
462
+ else:
463
+ self._decay = None
420
464
 
421
465
  @property
422
466
  def temperature(self):
@@ -435,6 +479,7 @@ class Memory(dict):
435
479
  if value is None or value is False:
436
480
  value = None
437
481
  else:
482
+ Memory.is_real(value, "temperature", True, True)
438
483
  value = float(value)
439
484
  t = Memory._validate_temperature(value, self._noise)
440
485
  if not t:
@@ -474,7 +519,8 @@ class Memory(dict):
474
519
 
475
520
  @threshold.setter
476
521
  def threshold(self, value):
477
- if value is None or value is False:
522
+ Memory.is_real(value, "threshold", False)
523
+ if value is None:
478
524
  self._threshold = None
479
525
  else:
480
526
  self._threshold = float(value)
@@ -497,17 +543,18 @@ class Memory(dict):
497
543
  ratios of various times, the :attr:`mismatch` is sensitive to the actual
498
544
  magnitude. Suitable care should be exercised when adjusting it.
499
545
 
500
- Attempting to set this parameter to a value other than ``None`` or a real number
501
- raises a :exc:`ValueError`.
546
+ Attempting to set this parameter to a value other than ``None`` or a non-negative
547
+ real number raises a :exc:`ValueError`.
502
548
  """
503
549
  return self._mismatch
504
550
 
505
551
  @mismatch.setter
506
552
  def mismatch(self, value):
507
- if value is None or value is False:
553
+ if value is False:
554
+ value = None
555
+ Memory.is_real(value, "mismatch")
556
+ if value is None:
508
557
  self._mismatch = None
509
- elif value < 0:
510
- raise ValueError(f"The mismatch penalty, {value}, must not be negative")
511
558
  else:
512
559
  self._mismatch = float(value)
513
560
 
@@ -989,7 +1036,12 @@ class Memory(dict):
989
1036
  "references": c.references,
990
1037
  "base_level_activation": r})
991
1038
  if self._noise:
992
- noise = self._rng.logistic(scale=self._noise, size=nchunks)
1039
+ if self._noise_distribution is not None:
1040
+ noise = self._noise * np.array([self._noise_distribution()
1041
+ for i in range(nchunks)],
1042
+ dtype=np.float64)
1043
+ else:
1044
+ noise = self._rng.logistic(scale=self._noise, size=nchunks)
993
1045
  if self._fixed_noise is not None:
994
1046
  if self._fixed_noise_time != self._time:
995
1047
  self._clear_fixed_noise()
@@ -10,7 +10,7 @@ setup(name="pyactup",
10
10
  description="A lightweight Python implementation of a subset of the ACT-R cognitive architecture’s Declarative Memory",
11
11
  author="Don Morrison",
12
12
  author_email="dfm2@cmu.edu",
13
- url="https://bitbucket.org/dfmorrison/pyactup/",
13
+ url="https://dfmorrison.github.io/pyactup-documentation/",
14
14
  platforms=["any"],
15
15
  long_description=DESCRIPTION,
16
16
  long_description_content_type="text/markdown",
@@ -18,7 +18,8 @@ setup(name="pyactup",
18
18
  install_requires=[
19
19
  "numpy",
20
20
  "pylru",
21
- "prettytable"],
21
+ "prettytable",
22
+ "packaging"],
22
23
  tests_require=["pytest"],
23
24
  python_requires=">=3.8",
24
25
  classifiers=["Intended Audience :: Science/Research",
File without changes
File without changes
File without changes