Categories
Uncategorized

[Algorithms][Final Exam Test Prep][python-ish] Find an algorithm that makes less than n*3/2 comparison to find the largest and smallest value in a list of n values.

This was a question I asked on reddit that I want to save

So I am looking over some past finals and this one kind-of sort-of stumped me, the question is:

Find an algorithm that makes less than n*3/2 comparison to find the largest and smallest value in a list of n values.

so I’m thinking Divide and Conquer approach, and I got the answer, however, it is for keys that fit the rule 2i + k where k is close to 0 and i is an integer. I’m not sure if there is another way of approaching the problem. to mess around with it, I decided to mock it up in python to test it out (which is where I determined that unless the number of items is close to function f(i) = 2i, it doesn’t really hold true)

import random

counter = [0]  # global, mutable counter for counting the number of comparisons


def file_min_max(F, n=None):
    if n is None:
        n = len(F)
    if n == 1:
        return F[0], F[0]
    elif n == 2:
        counter[0] += 1
        if F[0] < F[1]:
            return F[0], F[1]
        else:
            return F[1], F[0]
    else:
        mid = n//2
        left = file_min_max(F[0:mid])
        right = file_min_max(F[mid:n])
        counter[0] += 2
        if left[0] > right[0]:
            minimum = right[0]
        else:
            minimum = left[0]
        if left[len(left)-1] > right[len(right)-1]:
            maximum = right[len(left)-1]
        else:
            maximum = left[len(right)-1]
        return minimum, maximum

# unit testing
test_list = []
num = 2**10 + 0  # modify the number of elements here
for i in range(num):
    test_list.append(random.randint(0, num))
print(test_list)
print(file_min_max(test_list))
print(counter[0])
print(len(test_list))
print(counter[0]/len(test_list))


so my questions are:

1) is there another way of approaching this problem I didn’t see?

2) did I count my comparisons incorrectly?

also, as an aside, since this is a recursive function, I was using a mutable list as a counter. cumbersome, but it gets the job done. would there be a more efficient way of doing this?

Answer

Aha! Fun problem. Took me a while to get a better solution than what you have. Your solution looks good, but you’re right that it will be bigger than 3n/2 for numbers that aren’t close to a power of two.

You can do this instead:

Keep a record of the current smallest and largest number. If n is odd, set the first number to be biggest and smallest. If n is even, compare indexes 0 and 1 and mark the bigger as biggest and the smaller as smallest.

Compare the next pair of numbers to each other. Compare the smaller to the current smallest and the larger to the current largest. Note that this takes exactly 3 comparisons.

Continue doing this across the array. Bam! 3n/2 exactly! Or one or two comparisons cheaper if n is even.

P.S. Since this is an algorithms question, I would be remiss in pointing out that a naïve solution is still O(n), just as these are. So fun optimizations but not interesting from a complexity perspective.

Categories
Development Tools

Using python’s Pool.map() with many arguments

One thing that bugged me that took a while to find a solution was how to use multiple arguments in Python’s multiprocessing Pool.map(*) function.

def original_function(arg1, arg2, arg3, arg4)
    # do something with the four arguments
    return the_result

def function_wrapper(args):
    return original_function(*args)

def main()
    iterable = list()
    pool = mp.Pool()
    for parameter in parameters:
        iterable.append((arg1, arg2, arg3, parameter))
    results = list(pool.map(func=function_wrapper, iterable=iterable))

You are simply passing the tuple into a wrapper function and then unzipping the arguments inside the wrapper. Good enough for me.

Categories
Development Tools

Using Visual Studio 2017, CPLEX 12.8.0, Windows 10

To create the development environment that I anticipate for my research project, I wanted to ensure that I could get Visual Studio 2017 and CPLEX 12.8.0.  This project unfortunately took me the better part of a day, so I am documenting it here for my future reference and hopefully to save someone else some heartache.


To begin, I did use the material outlined in the post here.  However, the post is over a year old and the method outlined there did not yield a positive result.


Step 1: Updating the path variable

As outlined here, I updated my PATH variable.  I am not sure if it was absolutely necessary, as it was one of the first things I tried and was lazy to change it back.

As outlined in the steps from IBM, the PATH environment variable was already there so I added it by clicking “Edit…”.  The path of the dll is specifically:

C:\Program Files\IBM\ILOG\CPLEX_Studio128\cplex\bin\x64_win64

Step 2: Installing Visual Studio 2017, VC++ 2015.3 V140 toolset

If you have already installed Visual Studio 2017, you will need to re-run the Visual Studio Installer, for me it was in the Start Menu.  You will need to click “Modify”.  In the next menu, you will be in the “Workloads” tab.  Next to “Workloads”, click “Individual Components”.  Look for the header “Code Tools” under which will have the “VC++ 2015.3 V140 toolset for desktop (x86, x64)”.  Ensure that toolset is checked.  Click “Modify” in the lower right corner.  I believe it is a big file (approximately 8Gb).

If you are installing visual studio from scratch, I believe this is a similar process when you get to the choices for “Workloads”.  Choose your desired workloads and then go to the “Individual Components” tab.  Look for the header “Code Tools” and ensure the “VC++ 2015.3 V140 toolset for desktop (x86, x64)” is checked.


Step 3: Linking CPLEX with your Visual Studio project

For this step, I outright copied most of the steps outlined here.

to begin, right click on the the project file and entering the project properties.

Under C/C++, General, add the following to “Additional Include directories”

C:\Program Files\IBM\ILOG\CPLEX_Studio128\cplex\include 
C:\Program Files\IBM\ILOG\CPLEX_Studio128\concert\include

Under Linker, General, add the following to “Additional Library Directories”

Under the “Release Configuration”

C:\Program Files\IBM\ILOG\CPLEX_Studio128\cplex\lib\x64_windows_vs2017\stat_mda
C:\Program Files\IBM\ILOG\CPLEX_Studio128\concert\lib\x64_windows_vs2017\stat_mda

Under the “Debug Configuration”

C:\Program Files\IBM\ILOG\CPLEX_Studio128\cplex\lib\x64_windows_vs2017\stat_mdd
C:\Program Files\IBM\ILOG\CPLEX_Studio128\concert\lib\x64_windows_vs2017\stat_mdd

Under Linker, Inpurt, add the following to “Additional Dependencies”

cplex1280.lib
concert.lib
ilocplex.lib

And now Visual Studio should be able to call the CPLEX environment.