• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

j2kun / pmfp-code / 12979070715

26 Jan 2025 10:51PM UTC coverage: 99.574% (-0.3%) from 99.837%
12979070715

Pull #85

github

web-flow
Merge 1160c9064 into 7f9f6bc31
Pull Request #85: Tip for single sampling scheme

37 of 43 new or added lines in 1 file covered. (86.05%)

1870 of 1878 relevant lines covered (99.57%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.05
/tips/avoiding_defects.py
1
import random
1✔
2
from dataclasses import dataclass
1✔
3
from typing import Iterable, Union
1✔
4

5
import scipy.stats
1✔
6

7

8
@dataclass
1✔
9
class SingleSamplingScheme:
1✔
10
    # The number of items to sample from the lot
11
    sample_size: int
1✔
12

13
    # The maximum number of defective items in the sample before the lot is
14
    # rejected
15
    acceptance_number: int
1✔
16

17

18
# FIXME: convert to plotter function in __main__
19
def calculate_oc_hypergeom(
1✔
20
    sample_size: int,
21
    acceptance_number: int,
22
    population_size: int,
23
    defective_count: Union[int, Iterable[int]],
24
) -> Union[float, list[float]]:
25
    """Calculate the Operating Characteristic (OC) probability for a single-stage
26
    hypergeometric sampling plan.
27

28
    Returns float or list of floats computing the probability of accepting the lot given
29
    the sampling plan.
30
    """
NEW
31
    if not hasattr(defective_count, "__iter__"):
×
NEW
32
        defective_count = [defective_count]
×
33

NEW
34
    p_accept = [
×
35
        scipy.stats.hypergeom.cdf(
36
            k=acceptance_number,  # accept if we find <= c defects in the sample
37
            M=population_size,  # population size
38
            n=sample_size,  # sample size
39
            N=defects,  # number of defects in the population
40
        )
41
        for defects in defective_count
42
    ]
43

44
    # If input was single number, return single number
NEW
45
    if len(p_accept) == 1:
×
NEW
46
        return p_accept[0]
×
NEW
47
    return p_accept
×
48

49

50
def hypergeom(
1✔
51
    sample_size: int,
52
    acceptance_number: int,
53
    population_size: int,
54
    defective_count: int,
55
) -> float:
56
    """Calculate the hypergeometric function as used by the single sampling scheme."""
57
    return scipy.stats.hypergeom.cdf(
1✔
58
        k=acceptance_number,  # accept if we find <= c defects in the sample
59
        M=population_size,  # population size
60
        n=sample_size,  # sample size
61
        N=defective_count,  # number of defects in the population
62
    )
63

64

65
def find_plan_hypergeom(
1✔
66
    producer_risk_point: tuple[float, float],
67
    consumer_risk_point: tuple[float, float],
68
    population_size: int,
69
) -> tuple[int, int]:
70
    """Find the best single-scheme sampling plan.
71

72
    Args:
73
        producer_risk_point: (d, p) implying lots with defect rate <= d are
74
            accepted with probability >= p
75
        consumer_risk_point: (d, p) implying lots with defect rate >= d are
76
            accepted with probability <= p
77
        population_size: Size of the lot
78

79
    Returns: a tuple containing the best sample size and number of defects allowed.
80
    """
81
    assert 0 < producer_risk_point[0] < 1
1✔
82
    assert 0 < producer_risk_point[1] < 1
1✔
83
    assert 0 < consumer_risk_point[0] < 1
1✔
84
    assert 0 < consumer_risk_point[1] < 1
1✔
85

86
    defects_accepted = 0
1✔
87
    sample_size = defects_accepted + 1
1✔
88

89
    while True:
1✔
90
        prob_accept_bad_lot = hypergeom(
1✔
91
            sample_size=sample_size,
92
            acceptance_number=defects_accepted,
93
            population_size=population_size,
94
            defective_count=int(consumer_risk_point[0] * population_size),
95
        )
96
        prob_accept_good_lot = hypergeom(
1✔
97
            sample_size=sample_size,
98
            acceptance_number=defects_accepted,
99
            population_size=population_size,
100
            defective_count=int(producer_risk_point[0] * population_size),
101
        )
102

103
        if prob_accept_bad_lot > consumer_risk_point[1]:
1✔
104
            sample_size += 1  # Increase sample size to be more stringent
1✔
105
        elif prob_accept_good_lot < producer_risk_point[1]:
1✔
106
            defects_accepted += 1  # Allow one more defect to be more lenient
1✔
107
        else:
108
            # If both checks pass, the plan is good
109
            break
1✔
110

111
    return (sample_size, defects_accepted)
1✔
112

113

114
def simulate_single_sampling_scheme(
1✔
115
    population_size: int,
116
    actual_defective: int,
117
    plan: tuple[int, int],
118
    seed: int = 0,
119
    rounds: int = 1000,
120
):
121
    items = list(range(population_size))
1✔
122
    random.seed(seed)
1✔
123

124
    accepted_count = 0
1✔
125
    for i in range(rounds):
1✔
126
        defective_items = random.sample(items, actual_defective)
1✔
127
        sample = random.sample(items, plan[0])
1✔
128
        accepted = len(set(sample) & set(defective_items)) <= plan[1]
1✔
129
        accepted_count += int(accepted)
1✔
130

131
    return accepted_count / rounds
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc