Advertisement
Guest User

Untitled

a guest
Feb 8th, 2018
26
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.29 KB | None | 0 0
  1. from pulp import (
  2.     LpVariable, LpProblem, LpMinimize, value
  3. )
  4. from random import randint
  5.  
  6. # Make a memoization function
  7. def memoize(f):
  8.     class memocache(dict):
  9.         def __missing__(self, keys):
  10.             ret = self[keys] = f(*keys)
  11.             return ret
  12.         def __getitem__(self, *keys):
  13.             return dict.__getitem__(self, keys)
  14.     return memocache().__getitem__
  15.  
  16. # Make a function to discard unwanted integers
  17. def cap_ints(ints, n):
  18.     if max(ints) < n:
  19.         return ints
  20.     else:
  21.         ints_above = [i for i in ints if i > n]
  22.         smallest_above = min(ints_above)
  23.         return [i for i in ints if i <= smallest_above]
  24.  
  25. def find_sum_dp(ints, n):
  26.     # If n is in the list return n, or if the sum of ints is less than n
  27.     # return null
  28.     if n in ints:
  29.         return [n], n
  30.     elif sum(ints) < n:
  31.         return None, None
  32.     # Only search for values up to the smallest value above n
  33.     c = cap_ints(ints, n)
  34.     # Define the value function as a recurrent relation
  35.     @memoize
  36.     def V(n, i):
  37.         # If we've reached the end, don't do anything further
  38.         if i == 0 or n <= 0:
  39.             return 0.0, []
  40.         else:
  41.             # Calculate 2 cases: we use the current number, or we don't.
  42.             # a0 = don't take this integer, a1 = take this integer
  43.             # Get the results for the previous integer for each action
  44.             Va0_p, Sa0_p = V(n, i-1)
  45.             Va1_p, Sa1_p = V(n - c[i-1], i-1)
  46.             # Use for this integer's result
  47.             Va0, Sa0 = Va0_p, Sa0_p
  48.             Va1 = Va1_p + c[i-1] # Since we've taken this integer
  49.             Sa1 = Sa1_p + [c[i-1]] # Likewise
  50.             # We want the smallest value that exceeds or equals n.
  51.             # Since we assume our final state exceeds or equals n, at least Va1
  52.             # must exceed or equal n by this assumption.
  53.             if Va0 >= n and Va0 <= Va1:
  54.                 return Va0, Sa0
  55.             else:
  56.                 return Va1, Sa1
  57.  
  58.     sumsoln, soln = V(n, len(c))
  59.     return soln, sumsoln
  60.  
  61. def find_sum_lp(ints, n):
  62.     # If n is in the list return n, or if the sum of ints is less than n return
  63.     # null
  64.     if n in ints:
  65.         return [n], n
  66.     elif sum(ints) < n:
  67.         return None, None
  68.     # Only search for values up to the smallest value above n
  69.     c = cap_ints(ints, n)
  70.     L = len(c)
  71.     # Define the variables
  72.     variables = [
  73.         LpVariable("x"+str(i), 0, 1, cat='Binary') for i in xrange(L)
  74.     ]
  75.     # Define the problem
  76.     P = LpProblem("minsum", LpMinimize)
  77.     # Add constraint
  78.     P += sum(c[i]*variables[i] for i in range(L)) >= n
  79.     # Add objective function
  80.     P += sum(c[i]*variables[i] for i in range(L))
  81.     # Solve!
  82.     P.solve()
  83.     # Get the list of integers that are summed
  84.     soln = [
  85.         c[i] for i, xi in enumerate(variables)
  86.         if value(xi) == 1.0
  87.     ]
  88.     # Return the list of integers, and the sum
  89.     return soln, sum(soln)
  90.  
  91. def random_integers(lbound, ubound, length):
  92.     # Generate length random integers between lbound and ubound
  93.     return [randint(lbound, ubound) for i in xrange(length)]
  94.  
  95. if __name__ == '__main__':
  96.     ints = random_integers(1, 1000, 30)
  97.     n = 1000
  98.     print ints
  99.     print find_sum_lp(ints, n)
  100.     print find_sum_dp(ints, n)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement