random_utils.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #
  2. # Copyright 2019 The FATE Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. import array
  17. import functools
  18. import random
  19. import numpy as np
  20. from fate_arch.session import is_table
  21. def rand_tensor(q_field, tensor):
  22. if is_table(tensor):
  23. return tensor.mapValues(
  24. lambda x: np.array([random.randint(1, q_field) for _ in x], dtype=object))
  25. if isinstance(tensor, np.ndarray):
  26. arr = np.array([random.randint(1, q_field) for _ in tensor], dtype=object)
  27. return arr
  28. raise NotImplementedError(f"type={type(tensor)}")
  29. class _MixRand(object):
  30. def __init__(self, lower, upper, base_size=1000, inc_velocity=0.1, inc_velocity_deceleration=0.01):
  31. self._lower = lower
  32. if self._lower < 0:
  33. raise ValueError(f"lower should great than 0, found {self._lower}")
  34. self._upper = upper
  35. if self._upper < self._lower:
  36. raise ValueError(f"requires upper >= lower, yet upper={upper} and lower={lower}")
  37. if self._upper <= 0x40000000:
  38. self._caches = array.array('i')
  39. else:
  40. self._caches = array.array('l')
  41. # generate base random numbers
  42. for _ in range(base_size):
  43. self._caches.append(random.SystemRandom().randint(self._lower, self._upper))
  44. self._inc_rate = inc_velocity
  45. self._inc_velocity_deceleration = inc_velocity_deceleration
  46. def _inc(self):
  47. self._caches.append(random.SystemRandom().randint(self._lower, self._upper))
  48. def __next__(self):
  49. if random.random() < self._inc_rate:
  50. self._inc()
  51. return self._caches[random.randint(0, len(self._caches) - 1)]
  52. def __iter__(self):
  53. return self
  54. def _mix_rand_func(it, q_field):
  55. _mix = _MixRand(1, q_field)
  56. result = []
  57. for k, v in it:
  58. result.append((k, np.array([next(_mix) for _ in v], dtype=object)))
  59. return result
  60. def urand_tensor(q_field, tensor, use_mix=False):
  61. if is_table(tensor):
  62. if use_mix:
  63. return tensor.mapPartitions(functools.partial(_mix_rand_func, q_field=q_field),
  64. use_previous_behavior=False,
  65. preserves_partitioning=True)
  66. return tensor.mapValues(
  67. lambda x: np.array([random.SystemRandom().randint(1, q_field) for _ in x], dtype=object))
  68. if isinstance(tensor, np.ndarray):
  69. arr = np.zeros(shape=tensor.shape, dtype=object)
  70. view = arr.view().reshape(-1)
  71. for i in range(arr.size):
  72. view[i] = random.SystemRandom().randint(1, q_field)
  73. return arr
  74. raise NotImplementedError(f"type={type(tensor)}")