简体   繁体   中英

How can I do large permutations efficiently?

I'm in need of doing permutations on a list comprised of every value from 0 to 1, in 0.05 intervals.

I've already tried using itertools' permutations method (or function) but the program takes ages to get the permutation done and even crashes Spyder at it while I run it. I also need every number in each instance of the permutation to add up to 1 (example of this in the code snippet below). I can't even test the changes I make to the code since it would make my computer to stop working. Any suggestions?

weight.append(i for i in list(itertools.permutations(weights)) if sum(i)<=1.04 and sum(i)>=0.96) 

I did a double sum check because the sum of the numbers didn't exactly result in 1, so I couldn't just try if sum(i)==1 . This doesn't really append anything to the list I need it to append the results to, but that's a different issue.

Your comment revealed what you're after. It's not permutations, but Cartesian product .
In Python , that "translates" to [Python 3.Docs]: itertools. product ( *iterables, repeat=1 ) .

code.py :

#!/usr/bin/env python3

import sys
from itertools import product


def filter_values(values, min_sum=0, max_sum=100, count=3):
    for item in product(values, repeat=count):
        if min_sum <= sum(item) <= max_sum:
            yield item


def main():
    weights = [float(i) / 100 for i in range(0, 105, 5)]
    print("Weights: {:}\n".format(weights))

    filtered_weights = list(filter_values(weights, min_sum=0.96, max_sum=1.04))  # @TODO - cfati: !!! NOTA BENE: list(...) is for display purposes only! I guess its (disastrous) effects are quite familiar when it comes to large amounts of data !!!
    print("Filtering yielded {:d} elements".format(len(filtered_weights)))
    if (len(filtered_weights)):
        print("  First: {:}\n  Last: {:}".format(filtered_weights[0], filtered_weights[-1]))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()
    print("\nDone.")

Output :

 [cfati@CFATI-5510-0:e:\\Work\\Dev\\StackOverflow\\q056551640]> "e:\\Work\\Dev\\VEnvs\\py_064_03.07.03_test0\\Scripts\\python.exe" code.py Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32 Weights: [0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0] Filtering yielded 231 elements First: (0.0, 0.0, 1.0) Last: (1.0, 0.0, 0.0) Done. 

Given your precisions to the question (in the comments), you could get all these "permutations" using a simple list comprehension:

combos = [ (x/20,y/20,(20-x-y)/20) for x in range(21) for y in range(21-x) ]

# 231 combinations:
#
# [(0.0, 0.0, 1.0), (0.0, 0.05, 0.95), (0.0, 0.1, 0.9), (0.0, 0.15, 0.85), ... 
#  ... (0.95, 0.0, 0.05), (0.95, 0.05, 0.0), (1.0, 0.0, 0.0)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM