.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/random/plot_kiss_random.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite or Binder. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_random_plot_kiss_random.py: Enhanced KISS Random Generator - Complete Usage Examples ========================================================= .. currentmodule:: scikitplot.random Demonstrates all new features: 1. Auto-detection (Kiss64Random with None, 32, or 64) 2. Context manager support (with statement) 3. NumPy-like BitGenerator and Generator 4. State serialization/deserialization 5. Thread-safe operations .. GENERATED FROM PYTHON SOURCE LINES 19-46 .. code-block:: Python import time import pickle from concurrent.futures import ThreadPoolExecutor import matplotlib.pyplot as plt import numpy as np np.random.BitGenerator from scipy import stats # Import enhanced module from scikitplot.random import ( Kiss32Random, # Explicit 32-bit Kiss64Random, # Explicit 64-bit KissRandom, KissSeedSequence, KissBitGenerator, # NumPy-compatible BitGenerator KissGenerator, # High-level Generator KissRandomState, default_rng, # Convenience function kiss_context, # Context manager helper ) print("=" * 70) print("ENHANCED KISS RANDOM - NEW FEATURES DEMONSTRATION") print("=" * 70) .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== ENHANCED KISS RANDOM - NEW FEATURES DEMONSTRATION ====================================================================== .. GENERATED FROM PYTHON SOURCE LINES 47-150 .. code-block:: Python # Use time.perf_counter() or timeit import time import numpy as np seed = 42 n = 1_000_000 # times = [] # np.random.default_rng? # rng1 = np.random.default_rng(seed) # rng2 = default_rng(seed) # start = time.perf_counter() # seq1 = rng1.random(5) # end = time.perf_counter() # times.append(end - start) # start = time.perf_counter() # seq2 = rng2.random(5) # end = time.perf_counter() # times.append(end - start) # seq1, seq2, times def benchmark_rng( rng_factory, method_name: str = "random", seed: int = 42, repeat: int = 5, # size: int = 1_000_000, **kwargs, ): """ Benchmark an RNG method in a deterministic, isolated manner. Parameters ---------- rng_factory : callable Function that returns a new RNG instance when called with a seed. method_name : str RNG method to benchmark (e.g., "random"). seed : int Seed for reproducibility. repeat : int Number of benchmark repetitions. **kwargs : dict Returns ------- dict Timing statistics and output sanity checks. """ times = [] outputs = [] for _ in range(repeat): rng = rng_factory(seed) method = getattr(rng, method_name) start = time.perf_counter() out = method(**kwargs) end = time.perf_counter() times.append(end - start) outputs.append(out) times = np.asarray(times) outputs = np.asarray(outputs) return { "n": n, "repeat": repeat, "time_min": float(times.min()), "time_mean": float(times.mean()), "time_max": float(times.max()), "time_std": float(times.std(ddof=1)), "output_mean": float(outputs.mean()), "output_std": float(outputs.std(ddof=1)), } from functools import partial from pprint import pprint for method in ["random", "uniform"]: print("Numpy") numpy_result = benchmark_rng( rng_factory=np.random.default_rng, method_name=method, seed=seed, size = 1_000_000, ) pprint(numpy_result, sort_dicts=False) print("Kiss Customized 64") custom_result = benchmark_rng( # rng_factory=partial(default_rng, bit_width=32), rng_factory=default_rng, method_name=method, seed=seed, size = 1_000_000, ) pprint(custom_result, sort_dicts=False) .. rst-class:: sphx-glr-script-out .. code-block:: none Numpy {'n': 1000000, 'repeat': 5, 'time_min': 0.0037214869989838917, 'time_mean': 0.005170923199329991, 'time_max': 0.006321916000160854, 'time_std': 0.0012222408285072575, 'output_mean': 0.5000264761740889, 'output_std': 0.2886354529025341} Kiss Customized 64 {'n': 1000000, 'repeat': 5, 'time_min': 0.01309531700098887, 'time_mean': 0.014935487199545605, 'time_max': 0.016717925998818828, 'time_std': 0.0017618422608756772, 'output_mean': 0.4994983951235817, 'output_std': 0.28868033687878636} Numpy {'n': 1000000, 'repeat': 5, 'time_min': 0.004862694000621559, 'time_mean': 0.0058732769997732245, 'time_max': 0.007577533997391583, 'time_std': 0.0013320869110501237, 'output_mean': 0.5000264761740889, 'output_std': 0.2886354529025341} Kiss Customized 64 {'n': 1000000, 'repeat': 5, 'time_min': 0.014545681999152293, 'time_mean': 0.015888692400039872, 'time_max': 0.01843192899832502, 'time_std': 0.0016461476154398381, 'output_mean': 0.4994983951235817, 'output_std': 0.28868033687878636} .. GENERATED FROM PYTHON SOURCE LINES 151-176 .. code-block:: Python # =========================================================================== # Feature 1: Auto-Detection # =========================================================================== print("\n" + "=" * 70) print("1. AUTO-DETECTION (Kiss64Random factory)") print("=" * 70) # Explicit 32-bit rng_32 = Kiss32Random(seed=42) print(f"64-bit RNG: {rng_32}") print(f"Type: {type(rng_32).__name__}") # Explicit 64-bit rng_64 = Kiss64Random(seed=42) print(f"64-bit RNG: {rng_64}") print(f"Type: {type(rng_64).__name__}") # Generate some values print(f"\nGenerated values (auto):") print(f" kiss(): {rng_64.kiss()}") print(f" flip(): {rng_64.flip()}") print(f" index(100): {rng_64.index(100)}") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 1. AUTO-DETECTION (Kiss64Random factory) ====================================================================== 64-bit RNG: Kiss32Random Type: Kiss32Random 64-bit RNG: Kiss64Random Type: Kiss64Random Generated values (auto): kiss(): 5680804532875375661 flip(): 0 index(100): 38 .. GENERATED FROM PYTHON SOURCE LINES 177-216 .. code-block:: Python # =========================================================================== # Feature 2: Context Manager Support # =========================================================================== print("\n" + "=" * 70) print("2. CONTEXT MANAGER SUPPORT (with statement)") print("=" * 70) # Basic context manager usage print("Basic usage:") with Kiss64Random(42) as rng: values = [rng.kiss() for _ in range(5)] print(f" Generated 5 values: {values[:3]}...") # Nested context managers (independent RNGs) print("\nNested contexts (independent streams):") with Kiss64Random(100) as rng1: with Kiss64Random(200) as rng2: val1 = rng1.kiss() val2 = rng2.kiss() print(f" RNG1 (seed=100): {val1}") print(f" RNG2 (seed=200): {val2}") print(f" Different: {val1 != val2}") # Context manager ensures thread safety print("\nThread-safe access with context manager:") rng = Kiss64Random(42) def worker(thread_id): """Worker function using shared RNG.""" with rng: # Acquires lock return [rng.kiss() for _ in range(3)] with ThreadPoolExecutor(max_workers=2) as executor: results = list(executor.map(worker, range(2))) print(f" Thread 0: {results[0]}") print(f" Thread 1: {results[1]}") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 2. CONTEXT MANAGER SUPPORT (with statement) ====================================================================== Basic usage: Generated 5 values: [5680804532875375661, 421217147685971266, 15020224898898924438]... Nested contexts (independent streams): RNG1 (seed=100): 3951422275965105255 RNG2 (seed=200): 14327715817426728139 Different: True Thread-safe access with context manager: Thread 0: [5680804532875375661, 421217147685971266, 15020224898898924438] Thread 1: [16951546275468841018, 12649982757840217320, 1851205573436742921] .. GENERATED FROM PYTHON SOURCE LINES 217-258 .. code-block:: Python # =========================================================================== # Feature 3: NumPy-Compatible BitGenerator # =========================================================================== print("\n" + "=" * 70) print("3. NUMPY-LIKE BITGENERATOR") print("=" * 70) # Create BitGenerator bg = KissBitGenerator(seed=42) print(f"BitGenerator: {bg}") print(f"Has lock: {hasattr(bg, 'lock')}") # Generate raw bits raw_value = bg.random_raw() print(f"\nRaw uint64: {raw_value}") # Generate array of raw bits raw_array = bg.random_raw(size=5) print(f"Raw array: {raw_array}") # Use with NumPy Generator (if available) try: # Error not compat numpy C-Api # from numpy.random import Generator bg_numpy = KissBitGenerator(seed=123) gen = KissGenerator(bg_numpy) print("\n✅ Generator Integration:") print(f" Random floats: {gen.random(5)}") print(f" Random ints: {gen.integers(0, 100, size=5)}") # This gives access to ALL random methods! print(f" Normal: {gen.normal(size=5)}") print(f" Uniform: {gen.uniform(size=5)}") except ImportError: print("\n⚠️ Do not use NumPy Generator not available due to c-api inconsistency!") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 3. NUMPY-LIKE BITGENERATOR ====================================================================== BitGenerator: KissBitGenerator Has lock: True Raw uint64: 5680804532875375661 Raw array: [ 421217147685971266 15020224898898924438 16951546275468841018 12649982757840217320 1851205573436742921] ✅ Generator Integration: Random floats: [0.57358203 0.55408423 0.63089841 0.04077134 0.13284327] Random ints: [77 88 38 2 91] Normal: [ 0.35713156 -0.38265306 -0.36348331 0.94098378 -1.65821998] Uniform: [0.2203807 0.96561967 0.39410862 0.78222871 0.12790767] .. GENERATED FROM PYTHON SOURCE LINES 259-308 .. code-block:: Python # =========================================================================== # Feature 4: High-Level KissGenerator # =========================================================================== print("\n" + "=" * 70) print("4. HIGH-LEVEL KissGenerator") print("=" * 70) # Create generator (multiple ways) gen1 = KissGenerator() # From seed print(f"Generator from seed: {gen1}") bg = KissBitGenerator(seed=123) gen2 = KissGenerator(bg) # From BitGenerator print(f"Generator from BitGenerator: {gen2}") # Use all the methods print("\nGenerator methods:") # Random floats floats = gen1.random(5) print(f" random(5): {floats}") # Random integers ints = gen1.integers(0, 100, size=5) print(f" integers(0, 100): {ints}") # Normal distribution normal = gen1.normal(0, 1, size=5) print(f" normal(0, 1): {normal}") # Uniform distribution uniform = gen1.uniform(10, 20, size=5) print(f" uniform(10, 20): {uniform}") # Choice choices = gen1.choice(['A', 'B', 'C'], size=10) print(f" choice(['A','B','C']): {choices}") # Weighted choice choices_weighted = gen1.choice(['A', 'B', 'C'], size=100, p=[0.5, 0.3, 0.2]) print(f" Weighted choice A: {list(choices_weighted).count('A')}% (✅ expected ~50%)") # Shuffle arr = np.arange(10) gen1.shuffle(arr) print(f" shuffle([0..9]): {arr}") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 4. HIGH-LEVEL KissGenerator ====================================================================== Generator from seed: KissGenerator Generator from BitGenerator: KissGenerator Generator methods: random(5): [0.37472083 0.73688145 0.66996343 0.41081756 0.26912489] integers(0, 100): [92 41 86 15 92] normal(0, 1): [-1.61280274 -0.03472555 0.66032793 0.02331189 -0.23734106] uniform(10, 20): [10.13369613 18.94473886 16.4785329 11.91111733 14.7825545 ] choice(['A','B','C']): ['A' 'B' 'C' 'A' 'B' 'C' 'A' 'B' 'C' 'A'] Weighted choice A: 58% (✅ expected ~50%) shuffle([0..9]): [6 3 5 9 1 8 7 4 2 0] .. GENERATED FROM PYTHON SOURCE LINES 309-328 .. code-block:: Python # =========================================================================== # Feature 5: default_rng() Convenience Function # =========================================================================== print("\n" + "=" * 70) print("5. default_rng() CONVENIENCE FUNCTION") print("=" * 70) # Recommended way to create RNG (like numpy.random.default_rng) rng = default_rng(seed=42) print(f"Default RNG: {rng}") # Use it just like NumPy print("\nUsage:") print(f" Random floats: {rng.random(5)}") print(f" Random ints: {rng.integers(0, 10, size=5)}") print(f" Normal: {rng.normal(0, 1, size=5)}") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 5. default_rng() CONVENIENCE FUNCTION ====================================================================== Default RNG: KissGenerator Usage: Random floats: [0.30795703 0.02283423 0.81424802 0.91894516 0.68575694] Random ints: [1 9 6 4 2] Normal: [-2.43821743 -0.90688695 0.67830116 -0.09502604 1.004278 ] .. GENERATED FROM PYTHON SOURCE LINES 329-346 .. code-block:: Python # =========================================================================== # Feature 6: Context Manager Helper (kiss_context) # =========================================================================== print("\n" + "=" * 70) print("6. CONTEXT MANAGER HELPER (kiss_context)") print("=" * 70) # Convenient temporary RNG with kiss_context(seed=999) as rng: values = rng.random(5) print(f"Generated values: {values}") print(f"RNG type: {type(rng)}") print("RNG automatically cleaned up after context") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 6. CONTEXT MANAGER HELPER (kiss_context) ====================================================================== Generated values: [0.26108203 0.92908423 0.9072656 0.4323729 0.85688807] RNG type: RNG automatically cleaned up after context .. GENERATED FROM PYTHON SOURCE LINES 347-383 .. code-block:: Python # =========================================================================== # Feature 7: State Serialization/Deserialization # =========================================================================== print("\n" + "=" * 70) print("7. STATE SERIALIZATION/DESERIALIZATION") print("=" * 70) # Create RNG and generate some values rng1 = KissBitGenerator(seed=42) sequence1 = [rng1.random_raw() for _ in range(5)] print(f"Original sequence: {sequence1}") # Save state state = rng1.state print(f"\nSaved state: {state}") # Continue generating more_values = [rng1.random_raw() for _ in range(3)] print(f"Continued: {more_values}") # Restore from state rng2 = KissBitGenerator() rng2.__setstate__(state) sequence2 = [rng2.random_raw() for _ in range(5)] print(f"\nRestored sequence: {sequence2}") print(f"Sequences match: {sequence1 == sequence2} ✅") # Can also pickle/unpickle state # state_pickled = pickle.dumps(state) # state_restored = pickle.loads(state_pickled) # rng3 = Kiss64Random.from_state(state_restored) # sequence3 = [rng3.random_raw() for _ in range(5)] # print(f"Pickled/unpickled: {sequence1 == sequence3} ✅") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 7. STATE SERIALIZATION/DESERIALIZATION ====================================================================== Original sequence: [5680804532875375661, 421217147685971266, 15020224898898924438, 16951546275468841018, 12649982757840217320] Saved state: {'seed_sequence': 'KissSeedSequence', 'seed_sequence_state': {'seed': 42, 'seed_seq': {'entropy': 42, 'spawn_key': [], 'pool_size': 4, 'n_children_spawned': 0, '__version__': '0.0.0'}}, '__version__': '0.0.0'} Continued: [1851205573436742921, 1609824349404455259, 16565782244898480756] Restored sequence: [5680804532875375661, 421217147685971266, 15020224898898924438, 16951546275468841018, 12649982757840217320] Sequences match: True ✅ .. GENERATED FROM PYTHON SOURCE LINES 384-422 .. code-block:: Python # =========================================================================== # Feature 8: Thread-Safe Operations # =========================================================================== print("\n" + "=" * 70) print("8. THREAD-SAFE OPERATIONS") print("=" * 70) # Shared RNG with lock shared_rng = Kiss64Random(seed=42) def parallel_task(task_id): """Task that uses shared RNG safely.""" with shared_rng: # Acquire lock # Safe to use RNG here return { 'task_id': task_id, 'values': [shared_rng.kiss() for _ in range(3)] } print("Running 4 parallel tasks with shared RNG:") with ThreadPoolExecutor(max_workers=4) as executor: results = list(executor.map(parallel_task, range(4))) for result in results: print(f" Task {result['task_id']}: {result['values']}") # Verify no value duplication (all unique sequences) all_values = [] for result in results: all_values.extend(result['values']) unique_count = len(set(all_values)) total_count = len(all_values) print(f"\nTotal values: {total_count}, Unique: {unique_count}") print(f"All unique: {unique_count == total_count} ✅") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 8. THREAD-SAFE OPERATIONS ====================================================================== Running 4 parallel tasks with shared RNG: Task 0: [5680804532875375661, 421217147685971266, 15020224898898924438] Task 1: [16951546275468841018, 12649982757840217320, 1851205573436742921] Task 2: [1609824349404455259, 16565782244898480756, 16994184917449673914] Task 3: [2016129216417097342, 625761349625496807, 10268816598287657581] Total values: 12, Unique: 12 All unique: True ✅ .. GENERATED FROM PYTHON SOURCE LINES 423-468 .. code-block:: Python # =========================================================================== # Feature 9: Comparison with NumPy # =========================================================================== print("\n" + "=" * 70) print("9. COMPARISON WITH NUMPY (Statistical Validation)") print("=" * 70) # Generate large samples with both n_samples = 100000 # KISS kiss_gen = default_rng(42) kiss_samples = kiss_gen.random(n_samples) # NumPy numpy_gen = np.random.default_rng(42) numpy_samples = numpy_gen.random(n_samples) print(f"Generated {n_samples:,} samples with each") # Compare statistics print("\nStatistical comparison:") print(f" KISS - Mean: {kiss_samples.mean():.6f}, Std: {kiss_samples.std():.6f}") print(f" NumPy - Mean: {numpy_samples.mean():.6f}, Std: {numpy_samples.std():.6f}") print(f" Expected: Mean: 0.500000, Std: 0.288675") # Chi-square test from scipy import stats def chi_square_test(samples, n_bins=20): """Perform chi-square uniformity test.""" observed, _ = np.histogram(samples, bins=n_bins, range=(0, 1)) expected = np.full(n_bins, len(samples) / n_bins) chi2, p_value = stats.chisquare(observed, expected) return chi2, p_value chi2_kiss, p_kiss = chi_square_test(kiss_samples) chi2_numpy, p_numpy = chi_square_test(numpy_samples) print("\nChi-square uniformity test:") print(f" KISS: χ²={chi2_kiss:.2f}, p={p_kiss:.4f} {'✅ PASS' if p_kiss > 0.01 else '❌ FAIL'}") print(f" NumPy: χ²={chi2_numpy:.2f}, p={p_numpy:.4f} {'✅ PASS' if p_numpy > 0.01 else '❌ FAIL'}") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 9. COMPARISON WITH NUMPY (Statistical Validation) ====================================================================== Generated 100,000 samples with each Statistical comparison: KISS - Mean: 0.498611, Std: 0.288843 NumPy - Mean: 0.500625, Std: 0.288519 Expected: Mean: 0.500000, Std: 0.288675 Chi-square uniformity test: KISS: χ²=13.77, p=0.7969 ✅ PASS NumPy: χ²=16.66, p=0.6131 ✅ PASS .. GENERATED FROM PYTHON SOURCE LINES 469-508 .. code-block:: Python # =========================================================================== # Feature 10: Advanced Usage - Custom Distribution # =========================================================================== print("\n" + "=" * 70) print("10. ADVANCED USAGE - CUSTOM DISTRIBUTIONS") print("=" * 70) # Extend KissGenerator with custom methods class ExtendedKissGenerator(KissGenerator): """Extended generator with custom distributions.""" def exponential(self, scale=1.0, size=None): """Exponential distribution.""" u = self.random(size) return -scale * np.log(1 - u) def beta(self, alpha, beta_param, size=None): """Beta distribution (simplified).""" # Using rejection sampling (not optimal, just for demo) if size is None: while True: u1 = self.random() u2 = self.random() if u2 <= u1**(alpha-1) * (1-u1)**(beta_param-1): return u1 else: return np.array([self.beta(alpha, beta_param) for _ in range(size)]) # Use custom generator custom_gen = ExtendedKissGenerator() exp_samples = custom_gen.exponential(scale=2.0, size=5) print(f"Exponential(scale=2): {exp_samples}") beta_samples = custom_gen.beta(2, 5, size=5) print(f"Beta(2, 5): {beta_samples}") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 10. ADVANCED USAGE - CUSTOM DISTRIBUTIONS ====================================================================== Exponential(scale=2): [0.2298378 0.70586103 0.86556129 1.41513756 2.33343254] Beta(2, 5): [0.30107727 0.45391452 0.19265033 0.14310286 0.60782279] .. GENERATED FROM PYTHON SOURCE LINES 509-533 .. code-block:: Python # =========================================================================== # Feature 11: Reproducibility Across Platforms # =========================================================================== print("\n" + "=" * 70) print("11. REPRODUCIBILITY DEMO") print("=" * 70) # Same seed produces same sequence (always) seeds = [42, 123, 999] for seed in seeds: # Generate twice with same seed rng1 = default_rng(seed) seq1 = rng1.random(3) rng2 = default_rng(seed) seq2 = rng2.random(3) match = np.allclose(seq1, seq2) print(f"Seed {seed:>3}: {seq1} == {seq2} : {match} ✅") .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 11. REPRODUCIBILITY DEMO ====================================================================== Seed 42: [0.30795703 0.02283423 0.81424802] == [0.30795703 0.02283423 0.81424802] : True ✅ Seed 123: [0.57358203 0.55408423 0.63089841] == [0.57358203 0.55408423 0.63089841] : True ✅ Seed 999: [0.26108203 0.92908423 0.9072656 ] == [0.26108203 0.92908423 0.9072656 ] : True ✅ .. GENERATED FROM PYTHON SOURCE LINES 534-684 .. code-block:: Python # =========================================================================== # Visualization # =========================================================================== import numpy as np from scipy.signal import correlate from scipy.stats import norm def autocorrelation(x, nlags): """ Compute autocorrelation function up to nlags. Parameters ---------- x : array-like, shape (n_samples,) Input time series. nlags : int Maximum lag. Returns ------- lags : ndarray of shape (nlags + 1,) Lag indices. acf : ndarray of shape (nlags + 1,) Autocorrelation values. """ x = np.asarray(x, dtype=float) if x.ndim != 1: raise ValueError("Input must be 1D") if nlags < 0: raise ValueError("nlags must be non-negative") x = x - x.mean() n = x.size corr = correlate(x, x, mode="full") corr = corr[n - 1 : n + nlags] corr /= corr[0] lags = np.arange(nlags + 1) return lags, corr print("\n" + "=" * 70) print("12. VISUALIZATION") print("=" * 70) # Create comprehensive visualization fig, axes = plt.subplots(2, 3, figsize=(15, 8)) gen = default_rng(42) # 1. Uniform distribution ax = axes[0, 0] uniform_samples = gen.random(10000) ax.hist(uniform_samples, bins=50, density=True, alpha=0.7, edgecolor='black') ax.axhline(y=1.0, color='r', linestyle='--', alpha=0.7) ax.set_title('Uniform Distribution') ax.set_xlabel('Value') ax.set_ylabel('Density') ax.grid(True, alpha=0.3) # 2. Normal distribution ax = axes[0, 1] normal_samples = gen.normal(0, 1, size=10000) ax.hist(normal_samples, bins=50, density=True, alpha=0.7, edgecolor='black') x = np.linspace(-4, 4, 100) ax.plot(x, stats.norm.pdf(x), 'r--', linewidth=2, label='Theory') ax.set_title('Normal Distribution') ax.set_xlabel('Value') ax.set_ylabel('Density') ax.legend() ax.grid(True, alpha=0.3) # 3. Integer distribution ax = axes[0, 2] int_samples = gen.integers(0, 20, size=10000) ax.hist(int_samples, bins=20, density=True, alpha=0.7, edgecolor='black') ax.axhline(y=1/20, color='r', linestyle='--', alpha=0.7) ax.set_title('Integer Distribution [0, 20)') ax.set_xlabel('Value') ax.set_ylabel('Density') ax.grid(True, alpha=0.3) # 4. Q-Q plot ax = axes[1, 0] stats.probplot(uniform_samples, dist="uniform", plot=ax) ax.set_title('Q-Q Plot (Uniform)') ax.grid(True, alpha=0.3) # 5. Autocorrelation ax = axes[1, 1] # from statsmodels.graphics.tsaplots import plot_acf # plot_acf(uniform_samples[:1000], lags=40, ax=ax, alpha=0.05) # ax.set_title('Autocorrelation') # ax.grid(True, alpha=0.3) lags, acf = autocorrelation(uniform_samples[:1000], nlags=40) markerline, stemlines, baseline = ax.stem(lags, acf) plt.setp(markerline, markersize=4) plt.setp(stemlines, linewidth=1) plt.setp(baseline, linewidth=1) # Zero line ax.axhline(0.0, linewidth=1) # White-noise confidence interval bounds (same assumption as statsmodels) alpha = 0.05 n = 1000 z = norm.ppf(1 - alpha / 2) ci = z / np.sqrt(n) ax.axhline(ci, linestyle="--", linewidth=1) ax.axhline(-ci, linestyle="--", linewidth=1) # Filled confidence band ax.fill_between( lags, -ci, ci, alpha=0.2, step="mid" ) # Axis formatting ax.set_ylim(-1.0, 1.0) # ← explicit ACF bounds # ax.set_yticks(np.linspace(-1.0, 1.0, 5)) ax.set_title("Autocorrelation") ax.set_xlabel("Lag") ax.set_ylabel("ACF") ax.grid(True, alpha=0.3) # 6. 2D scatter (independence test) ax = axes[1, 2] ax.scatter(uniform_samples[:-1], uniform_samples[1:], alpha=0.1, s=1) ax.set_title('Serial Independence Test') ax.set_xlabel('X[i]') ax.set_ylabel('X[i+1]') ax.grid(True, alpha=0.3) plt.suptitle('Enhanced KISS Random Generator - Statistical Validation', fontsize=14, fontweight='bold') plt.tight_layout() plt.savefig('/tmp/enhanced_kiss_validation.png', dpi=150, bbox_inches='tight') print("Visualization saved: /tmp/enhanced_kiss_validation.png") plt.show() # plt.close() .. image-sg:: /auto_examples/random/images/sphx_glr_plot_kiss_random_001.png :alt: Enhanced KISS Random Generator - Statistical Validation, Uniform Distribution, Normal Distribution, Integer Distribution [0, 20), Q-Q Plot (Uniform), Autocorrelation, Serial Independence Test :srcset: /auto_examples/random/images/sphx_glr_plot_kiss_random_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== 12. VISUALIZATION ====================================================================== Visualization saved: /tmp/enhanced_kiss_validation.png .. GENERATED FROM PYTHON SOURCE LINES 685-712 .. code-block:: Python # =========================================================================== # Summary # =========================================================================== print("\n" + "=" * 70) print("SUMMARY - ALL FEATURES DEMONSTRATED") print("=" * 70) summary = """ RECOMMENDED USAGE: from scikitplot.random import default_rng # Create generator rng = default_rng(seed=42) data = rng.random(1000) # Use with context manager for safety with rng: samples = rng.random(1000) indices = rng.integers(0, 100, size=50) normal_data = rng.normal(0, 1, size=1000) """ print(summary) print("=" * 70) .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== SUMMARY - ALL FEATURES DEMONSTRATED ====================================================================== RECOMMENDED USAGE: from scikitplot.random import default_rng # Create generator rng = default_rng(seed=42) data = rng.random(1000) # Use with context manager for safety with rng: samples = rng.random(1000) indices = rng.integers(0, 100, size=50) normal_data = rng.normal(0, 1, size=1000) ====================================================================== .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 3.674 seconds) .. _sphx_glr_download_auto_examples_random_plot_kiss_random.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: binder-badge .. image:: images/binder_badge_logo.svg :target: https://mybinder.org/v2/gh/scikit-plots/scikit-plots/main?urlpath=lab/tree/notebooks/auto_examples/random/plot_kiss_random.ipynb :alt: Launch binder :width: 150 px .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../lite/lab/index.html?path=auto_examples/random/plot_kiss_random.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_kiss_random.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_kiss_random.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_kiss_random.zip ` .. include:: plot_kiss_random.recommendations .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_