File: utilities.py

package info (click to toggle)
python-pulp 2.6.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 14,720 kB
  • sloc: python: 7,505; makefile: 16; sh: 16
file content (232 lines) | stat: -rw-r--r-- 6,138 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# Utility functions
import itertools
import collections


def resource_clock():
    import resource

    return resource.getrusage(resource.RUSAGE_CHILDREN).ru_utime


def isNumber(x):
    """Returns true if x is an int or a float"""
    return isinstance(x, (int, float))


def value(x):
    """Returns the value of the variable/expression x, or x if it is a number"""
    if isNumber(x):
        return x
    else:
        return x.value()


def valueOrDefault(x):
    """Returns the value of the variable/expression x, or x if it is a number
    Variable without value (None) are affected a possible value (within their
    bounds)."""
    if isNumber(x):
        return x
    else:
        return x.valueOrDefault()


def __combination(orgset, k):
    """
    fall back if probstat is not installed note it is GPL so cannot
    be included
    """
    if k == 1:
        for i in orgset:
            yield (i,)
    elif k > 1:
        for i, x in enumerate(orgset):
            # iterates though to near the end
            for s in __combination(orgset[i + 1 :], k - 1):
                yield (x,) + s


try:  # python >= 3.4
    from itertools import combinations as combination
except ImportError:
    try:  # python 2.7
        from itertools import combination
    except ImportError:  # pulp's
        combination = __combination


def __permutation(orgset, k):
    """
    fall back if probstat is not installed note it is GPL so cannot
    be included
    """
    if k == 1:
        for i in orgset:
            yield (i,)
    elif k > 1:
        for i, x in enumerate(orgset):
            # iterates though to near the end
            for s in __permutation(orgset[:i] + orgset[i + 1 :], k - 1):
                yield (x,) + s


try:  # python >= 3.4
    from itertools import permutations as permutation
except ImportError:
    try:  # python 2.7
        from itertools import permutation
    except ImportError:  # pulp's
        permutation = __permutation


def allpermutations(orgset, k):
    """
    returns all permutations of orgset with up to k items

    :param orgset: the list to be iterated
    :param k: the maxcardinality of the subsets

    :return: an iterator of the subsets

    example:

    >>> c = allpermutations([1,2,3,4],2)
    >>> for s in c:
    ...     print(s)
    (1,)
    (2,)
    (3,)
    (4,)
    (1, 2)
    (1, 3)
    (1, 4)
    (2, 1)
    (2, 3)
    (2, 4)
    (3, 1)
    (3, 2)
    (3, 4)
    (4, 1)
    (4, 2)
    (4, 3)
    """
    return itertools.chain(*[permutation(orgset, i) for i in range(1, k + 1)])


def allcombinations(orgset, k):
    """
    returns all combinations of orgset with up to k items

    :param orgset: the list to be iterated
    :param k: the maxcardinality of the subsets

    :return: an iterator of the subsets

    example:

    >>> c = allcombinations([1,2,3,4],2)
    >>> for s in c:
    ...     print(s)
    (1,)
    (2,)
    (3,)
    (4,)
    (1, 2)
    (1, 3)
    (1, 4)
    (2, 3)
    (2, 4)
    (3, 4)
    """
    return itertools.chain(*[combination(orgset, i) for i in range(1, k + 1)])


def makeDict(headers, array, default=None):
    """
    makes a list into a dictionary with the headings given in headings
    headers is a list of header lists
    array is a list with the data
    """
    result, defdict = __makeDict(headers, array, default)
    return result


def __makeDict(headers, array, default=None):
    # this is a recursive function so end the recursion as follows
    result = {}
    returndefaultvalue = None
    if len(headers) == 1:
        result.update(dict(zip(headers[0], array)))
        defaultvalue = default
    else:
        for i, h in enumerate(headers[0]):
            result[h], defaultvalue = __makeDict(headers[1:], array[i], default)
    if default is not None:
        f = lambda: defaultvalue
        defresult = collections.defaultdict(f)
        defresult.update(result)
        result = defresult
        returndefaultvalue = collections.defaultdict(f)
    return result, returndefaultvalue


def splitDict(data):
    """
    Split a dictionary with lists as the data, into smaller dictionaries

    :param data: A dictionary with lists as the values

    :return: A tuple of dictionaries each containing the data separately,
            with the same dictionary keys
    """
    # find the maximum number of items in the dictionary
    maxitems = max([len(values) for values in data.values()])
    output = [dict() for _ in range(maxitems)]
    for key, values in data.items():
        for i, val in enumerate(values):
            output[i][key] = val

    return tuple(output)


def read_table(data, coerce_type, transpose=False):
    """
    Reads in data from a simple table and forces it to be a particular type

    This is a helper function that allows data to be easily constained in a
    simple script
    ::return: a dictionary of with the keys being a tuple of the strings
       in the first row and colum of the table
    ::param data: the multiline string containing the table data
    ::param coerce_type: the type that the table data is converted to
    ::param transpose: reverses the data if needed

    Example:
    >>> table_data = '''
    ...         L1      L2      L3      L4      L5      L6
    ... C1      6736    42658   70414   45170   184679  111569
    ... C2      217266  227190  249640  203029  153531  117487
    ... C3      35936   28768   126316  2498    130317  74034
    ... C4      73446   52077   108368  75011   49827   62850
    ... C5      174664  177461  151589  153300  59916   135162
    ... C6      186302  189099  147026  164938  149836  286307
    ... '''
    >>> table = read_table(table_data, int)
    >>> table[("C1","L1")]
    6736
    >>> table[("C6","L5")]
    149836
    """
    lines = data.splitlines()
    headings = lines[1].split()
    result = {}
    for row in lines[2:]:
        items = row.split()
        for i, item in enumerate(items[1:]):
            if transpose:
                key = (headings[i], items[0])
            else:
                key = (items[0], headings[i])
            result[key] = coerce_type(item)
    return result