Obtain ``a`` and ``b`` when ``e == "a*x+b"``, where ``x`` is a symbol in xset. >>> getlincoef('2*x + 1', {'x'}) (2, 1, 'x') >>> getlincoef('3*x + x*2 + 2 + 1', {'x'}) (5, 3, 'x') >>> getlincoef('0', {'x'}) (0, 0, None) >>> getlincoef('0*x', {'x'}) (0, 0, 'x'
(e, xset)
| 2309 | |
| 2310 | |
| 2311 | def getlincoef(e, xset): # e = a*x+b ; x in xset |
| 2312 | """ |
| 2313 | Obtain ``a`` and ``b`` when ``e == "a*x+b"``, where ``x`` is a symbol in |
| 2314 | xset. |
| 2315 | |
| 2316 | >>> getlincoef('2*x + 1', {'x'}) |
| 2317 | (2, 1, 'x') |
| 2318 | >>> getlincoef('3*x + x*2 + 2 + 1', {'x'}) |
| 2319 | (5, 3, 'x') |
| 2320 | >>> getlincoef('0', {'x'}) |
| 2321 | (0, 0, None) |
| 2322 | >>> getlincoef('0*x', {'x'}) |
| 2323 | (0, 0, 'x') |
| 2324 | >>> getlincoef('x*x', {'x'}) |
| 2325 | (None, None, None) |
| 2326 | |
| 2327 | This can be tricked by sufficiently complex expressions |
| 2328 | |
| 2329 | >>> getlincoef('(x - 0.5)*(x - 1.5)*(x - 1)*x + 2*x + 3', {'x'}) |
| 2330 | (2.0, 3.0, 'x') |
| 2331 | """ |
| 2332 | try: |
| 2333 | c = int(myeval(e, {}, {})) |
| 2334 | return 0, c, None |
| 2335 | except Exception: |
| 2336 | pass |
| 2337 | if getlincoef_re_1.match(e): |
| 2338 | return 1, 0, e |
| 2339 | len_e = len(e) |
| 2340 | for x in xset: |
| 2341 | if len(x) > len_e: |
| 2342 | continue |
| 2343 | if re.search(r'\w\s*\([^)]*\b' + x + r'\b', e): |
| 2344 | # skip function calls having x as an argument, e.g max(1, x) |
| 2345 | continue |
| 2346 | re_1 = re.compile(r'(?P<before>.*?)\b' + x + r'\b(?P<after>.*)', re.I) |
| 2347 | m = re_1.match(e) |
| 2348 | if m: |
| 2349 | try: |
| 2350 | m1 = re_1.match(e) |
| 2351 | while m1: |
| 2352 | ee = '%s(%s)%s' % ( |
| 2353 | m1.group('before'), 0, m1.group('after')) |
| 2354 | m1 = re_1.match(ee) |
| 2355 | b = myeval(ee, {}, {}) |
| 2356 | m1 = re_1.match(e) |
| 2357 | while m1: |
| 2358 | ee = '%s(%s)%s' % ( |
| 2359 | m1.group('before'), 1, m1.group('after')) |
| 2360 | m1 = re_1.match(ee) |
| 2361 | a = myeval(ee, {}, {}) - b |
| 2362 | m1 = re_1.match(e) |
| 2363 | while m1: |
| 2364 | ee = '%s(%s)%s' % ( |
| 2365 | m1.group('before'), 0.5, m1.group('after')) |
| 2366 | m1 = re_1.match(ee) |
| 2367 | c = myeval(ee, {}, {}) |
| 2368 | # computing another point to be sure that expression is linear |