Secretary Problem (A Optimal Stopping Problem)

04 Sep, 2019
The Secretary Problem also known as marriage problem, the sultan’s dowry problem, and the best choice problem is an example of Optimal Stopping Problem.
This problem can be stated in the following form: Imagine an administrator who wants to hire the best secretary out of n rankable applicants for a position. The applicants are interviewed one by one in random order. A decision about each particular applicant is to be made immediately after the interview. Once rejected, an applicant cannot be recalled. During the interview, the administrator can rank the applicant among all applicants interviewed so far but is unaware of the quality of yet unseen applicants. The question is about the optimal strategy (stopping rule) to maximize the probability of selecting the best applicant.
Optimal Stopping : In mathematics, the theory of optimal stopping or early stopping is concerned with the problem of choosing a time to take a particular action, in order to maximize an expected reward or minimize an expected cost.
If the decision to hire an applicant was to be taken in the end of interviewing all the n candidates, a simple solution is to use maximum selection algorithm of tracking the running maximum (and who achieved it) and selecting the overall maximum at the end. The difficult part of this problem is that the decision must be made immediately after interviewing a candidate.
1/e law of Optimal StrategyAccording to this strategy, the optimal win probability is always at least 1/e.The optimal stopping rule prescribes always rejecting the first n/e applicants that are interviewed (where e is the base of the natural logarithm and has the value 2.71828) and then stopping at the first applicant who is better than every applicant interviewed so far (or continuing to the last applicant if this never occurs). This strategy is called the 1/e stopping rule because the probability to select the best candidate is 1/e, in other words, this strategy selects the best candidate about 37% of time.
If you think carefully, it might seem obvious that one cannot select the first candidate because the first candidate has no one to compare with. A better strategy is to choose a few candidates as a sample to set the benchmark for remaining candidates. So the sample will be rejected and will only be used for setting benchmark.
If a sample is too small, we don’t get information enough for setting the benchmark for remaining candidates.
If a sample is too large, though we get plenty of information but we have also burned too many of the potential candidates. This leaves us with very few candidates to choose from, and hence making the strategy a poor one.
The best strategy is to choose the perfect or optimal sample size (ideal sample size) which can be done using 1/e law that is rejecting n/e candidates (this n/e is the sample size).
The optimal sample size and Probability of success for different values of n are :Optimal Sample size k = n / eProbability of success is given by :where x = k / n
The probability of selecting the best applicant in the classical secretary problem converges toward 1/e = 0.368 (approx)
Program to Test Secertary Problem :Note* : The Optimal Strategy doesn’t always find the best candidate but selects the almost best candidates most of the times.
C++
Java
Python3
C#
PHP
// C++ Program to test 1/e law for Secretary Problem :#include <iostream>#include <time.h>#define e 2.71828using namespace std;  // To find closest integer of num.int roundNo(float num){    return num < 0 ? num - 0.5 : num + 0.5;}  // Finds best candidate using n/e rule. candidate[]// represents talents of n candidates.void printBestCandidate(int candidate[], int n){    // Calculating sample size for benchmarking.    int sample_size = roundNo(n/e);    cout << "\n\nSample size is " << sample_size << endl;      // Finding best candidate in sample size    int best = 0;     for (int i = 1; i < sample_size; i++)        if (candidate[i] > candidate[best])            best = i;      // Finding the first best candidate that is      // better than benchmark set.    for (int i = sample_size; i < n; i++)        if (candidate[i] >= candidate[best]) {            best = i;            break;        }      if (best >= sample_size)        cout << endl << "Best candidate found is "            << best + 1 << " with talent "             << candidate[best] << endl;    else        cout << "Couldn't find a best candidate\n";}  int main(){    int n = 8;      // n = 8 candidates and candidate array contains    // talents of n candidate where the largest     // number means highest talented candidate.    int candidate[n];      // generating random numbers between 1 to 8     // for talent of candidate    srand(time(0));        for (int i = 0; i < n; i++)        candidate[i] = 1 + rand() % 8;      cout << "Candidate : ";    for (int i = 0; i < n; i++)        cout << i + 1 << " ";    cout << endl;    cout << "  Talents : ";    for (int i = 0; i < n; i++)        cout << candidate[i] << " ";          printBestCandidate(candidate, n);      return 0;}
// Java Program to test 1/e law for Secretary Problem :import java.util.*;class GFG{static double e = 2.71828;  // To find closest integer of num.static int roundNo(float num){    return (int) (num < 0 ?                   num - 0.5 : num + 0.5);}  // Finds best candidate using n/e rule. candidate[]// represents talents of n candidates.static void printBestCandidate(int candidate[], int n){    // Calculating sample size for benchmarking.    int sample_size = roundNo((float) (n / e));    System.out.println("\n\nSample size is " + sample_size);      // Finding best candidate in sample size    int best = 0;     for (int i = 1; i < sample_size; i++)        if (candidate[i] > candidate[best])            best = i;      // Finding the first best candidate that is     // better than benchmark set.    for (int i = sample_size; i < n; i++)        if (candidate[i] >= candidate[best])        {            best = i;            break;        }      if (best >= sample_size)        System.out.println("\nBest candidate found is " +                            (best + 1) + " with talent " +                             candidate[best]);    else        System.out.print("Couldn't find a best candidate\n");}  // Driver Codepublic static void main(String[] args){    int n = 8;      // n = 8 candidates and candidate array contains    // talents of n candidate where the largest     // number means highest talented candidate.    int []candidate = new int[n];      // generating random numbers between 1 to 8     // for talent of candidate    Random rand = new Random();    for (int i = 0; i < n; i++)        candidate[i] = 1 + rand.nextInt((8 - 1) + 1);      System.out.print("Candidate : ");    for (int i = 0; i < n; i++)        System.out.print(i + 1 + " ");    System.out.println();    System.out.print("Talents : ");    for (int i = 0; i < n; i++)        System.out.print(candidate[i] + " ");          printBestCandidate(candidate, n);}}  // This code is contributed by 29AjayKumar
# Python3 Program to test 1/e law for# Secretary Problemimport randomimport math  e = 2.71828;  # To find closest integer of num.def roundNo(num):    if(num < 0):         return (num - 0.5)    else:         return (num + 0.5);  # Finds best candidate using n/e rule. # candidate[] represents talents of n candidates.def printBestCandidate(candidate, n):          # Calculating sample size for benchmarking.    sample_size = roundNo(n / e);    print("\n\nSample size is",            math.floor(sample_size));      # Finding best candidate in sample size    best = 0;     for i in range(1, int(sample_size)):        if (candidate[i] > candidate[best]):            best = i;      # Finding the first best candidate that     # is better than benchmark set.    for i in range(int(sample_size), n):        if (candidate[i] >= candidate[best]):            best = i;            break;      if (best >= int(sample_size)):        print("\nBest candidate found is",                      math.floor(best + 1),               "with talent", math.floor(candidate[best]));    else:        print("Couldn't find a best candidate");  # Driver coden = 8;  # n = 8 candidates and candidate # array contains talents of n # candidate where the largest # number means highest talented # candidate.candidate = [0] * (n);  # generating random numbers between 1 to 8 # for talent of candidatefor i in range(n):    candidate[i] = 1 + random.randint(1, 8);print("Candidate : ", end = "");  for i in range(n):    print((i + 1), end = " ");print("\nTalents : ", end = "");  for i in range(n):    print(candidate[i], end = " ");   printBestCandidate(candidate, n);  # This code is contributed by mits
// C# Program to test 1/e law for Secretary Problemusing System;      class GFG{static double e = 2.71828;  // To find closest integer of num.static int roundNo(float num){    return (int) (num < 0 ?                   num - 0.5 : num + 0.5);}  // Finds best candidate using n/e rule. candidate[]// represents talents of n candidates.static void printBestCandidate(int []candidate, int n){    // Calculating sample size for benchmarking.    int sample_size = roundNo((float) (n / e));    Console.WriteLine("\n\nSample size is " +                                 sample_size);      // Finding best candidate in sample size    int best = 0;     for (int i = 1; i < sample_size; i++)        if (candidate[i] > candidate[best])            best = i;      // Finding the first best candidate that is     // better than benchmark set.    for (int i = sample_size; i < n; i++)        if (candidate[i] >= candidate[best])        {            best = i;            break;        }      if (best >= sample_size)        Console.WriteLine("\nBest candidate found is " +                           (best + 1) + " with talent " +                                        candidate[best]);    else        Console.Write("Couldn't find a best candidate\n");}  // Driver Codepublic static void Main(String[] args){    int n = 8;      // n = 8 candidates and candidate array contains    // talents of n candidate where the largest     // number means highest talented candidate.    int []candidate = new int[n];      // generating random numbers between 1 to 8     // for talent of candidate    Random rand = new Random();    for (int i = 0; i < n; i++)        candidate[i] = 1 + rand.Next(1, 8);      Console.Write("Candidate : ");    for (int i = 0; i < n; i++)        Console.Write(i + 1 + " ");    Console.WriteLine();    Console.Write("Talents : ");    for (int i = 0; i < n; i++)        Console.Write(candidate[i] + " ");          printBestCandidate(candidate, n);}}  // This code is contributed by Princi Singh
<?php// PHP Program to test 1/e // law for Secretary Problem :  $e = 2.71828;  // To find closest // integer of num.function roundNo($num){    return $num < 0 ?          $num - 0.5 : $num + 0.5;}  // Finds best candidate using // n/e rule. candidate[] // represents talents of n candidates.function printBestCandidate($candidate, $n){    global $e;          // Calculating sample size     // for benchmarking.    $sample_size = roundNo($n / $e);    echo "\n\nSample size is " .            floor($sample_size) . "\n";      // Finding best candidate    // in sample size    $best = 0;     for ($i = 1; $i < $sample_size; $i++)        if ($candidate[$i] >             $candidate[$best])            $best = $i;      // Finding the first best     // candidate that is better    // than benchmark set.    for ($i = $sample_size; $i < $n; $i++)        if ($candidate[$i] >=             $candidate[$best])        {            $best = $i;            break;        }      if ($best >= $sample_size)        echo "\nBest candidate found is " .                          floor($best + 1) .                           " with talent " .                  floor($candidate[$best]) . "\n";    else        echo "Couldn't find a best candidate\n";}  // Driver code$n = 8;  // n = 8 candidates and candidate // array contains talents of n // candidate where the largest // number means highest talented // candidate.$candidate = array_fill(0, $n, 0);  // generating random numbers // between 1 to 8 for talent// of candidatefor ($i = 0; $i < $n; $i++)    $candidate[$i] = 1 + rand(1, 8);echo "Candidate : ";  for ($i = 0; $i < $n; $i++)    echo ($i + 1) . " ";echo "\n Talents : ";  for ($i = 0; $i < $n; $i++)    echo $candidate[$i] . " ";  printBestCandidate($candidate, $n);  // This code is contributed by mits?>
Candidates : 1 2 3 4 5 6 7 8 
  Talents  : 5 3 8 6 5 7 8 6 

Sample size is 3

Best candidate found is 7 with talent 8

Alternate Optimal Strategy : This strategy instead of choosing the sample size as n/e, it selects square root of n as the optimal sample size (i.e. sqrt(n)).
This article is contributed by Shubham Rana. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Mithun Kumar
ManasChhabra2
29AjayKumar
princi singh
statistical-algorithms
Mathematical
Mathematical
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.