Clicky

🔮 NetworkX and Python Futures

Note: This post was updated to work with NetworkX and for clarity. It’s possible this will turn out like the day when Python 2.5 introduced [coroutines][coroutines]. At the time I was very excited. I spent several hours trying to convince my coworkers we should immediately abandon all our existing Java infrastructure and port it to finite state machines implemented using Python coroutines. After a day of hand waving over a proof of concept, we put that idea aside and went about our lives. ...

May 19, 2011 · Ryan O'Neil

👉 Affine Scaling in R

I recently stumbled across an implementation of the affine scaling interior point method for solving linear programs that I’d coded up in R once upon a time. I’m posting it here in case anyone else finds it useful. There’s not a whole lot of thought given to efficiency or numerical stability, just a demonstration of the basic algorithm. Still, sometimes that’s exactly what one wants. solve.affine <- function(A, rc, x, tolerance=10^-7, R=0.999) { # Affine scaling method while (T) { X_diag <- diag(x) # Compute (A * X_diag^2 * A^t)-1 using Cholesky factorization. # This is responsible for scaling the original problem matrix. q <- A %*% X_diag**2 %*% t(A) q_inv <- chol2inv(chol(q)) # lambda = q * A * X_diag^2 * c lambda <- q_inv %*% A %*% X_diag^2 %*% rc # c - A^t * lambda is used repeatedly foo <- rc - t(A) %*% lambda # We converge as s goes to zero s <- sqrt(sum((X_diag %*% foo)^2)) # Compute new x x <- (x + R * X_diag^2 %*% foo / s)[,] # If s is within our tolerance, stop. if (abs(s) < tolerance) break } x } This function accepts a matrix A which contains all technological coefficients for an LP, a vector rc containing its reduced costs, and an initial point x interior to the LP’s feasible region. Optional arguments to the function include a tolerance, for detecting when the method is within an acceptable distance from the optimal point, and a value for R, which must be strictly between 0 and 1 and controls scaling. ...

April 27, 2011 · Ryan O'Neil

🐪 Reformed JAPHs: Transpiler

Note: This post was edited for clarity. For the final JAPH in this series, I implemented a simple transpiler that converts a small subset of Scheme programs to equivalent Python programs. It starts with a Scheme program that prints 'just another scheme hacker'. (define (output x) (if (null? x) "" (begin (display (car x)) (if (null? (cdr x)) (display "\n") (begin (display " ") (output (cdr x))))))) (output (list "just" "another" "scheme" "hacker")) The program then tokenizes that Scheme source, parses the token stream, and converts that into Python 3. ...

April 20, 2011 · Ryan O'Neil

🐪 Reformed JAPHs: Turing Machine

Note: This post was edited for clarity. This JAPH uses a Turing machine. The machine accepts any string that ends in '\n' and allows side effects. This lets us print the value of the tape as it encounters each character. While the idea of using lambda functions as side effects in a Turing machine is a little bizarre on many levels, we work with what we have. And Python is multi-paradigmatic, so what the heck. ...

April 18, 2011 · Ryan O'Neil

🐪 Reformed JAPHs: Huffman Coding

Note: This post was edited for clarity. At this point, tricking python into printing strings via indirect means got a little boring. So I switched to obfuscating fundamental computer science algorithms. Here’s a JAPH that takes in a Huffman coded version of 'just another python hacker', decodes, and prints it. # Build coding tree def build_tree(scheme): if scheme.startswith('*'): left, scheme = build_tree(scheme[1:]) right, scheme = build_tree(scheme) return (left, right), scheme else: return scheme[0], scheme[1:] def decode(tree, encoded): ret = '' node = tree for direction in encoded: if direction == '0': node = node[0] else: node = node[1] if isinstance(node, str): ret += node node = tree return ret tree = build_tree('*****ju*sp*er***yct* h**ka*no')[0] print( decode(tree, bin(10627344201836243859174935587).lstrip('0b').zfill(103)) ) The decoding tree is like a LISP-style sequence of pairs. '*' represents a branch in the tree while other characters are leaf nodes. This looks like the following. ...

April 14, 2011 · Ryan O'Neil

🐪 Reformed JAPHs: Rolling Effect

Note: This post was updated to work with Python 3.12. It may not work with different versions. Here’s a JAPH composed solely for effect. For each letter in 'just another python hacker' it loops over each the characters ' abcdefghijklmnopqrstuvwxyz', printing each. Between characters it pauses for 0.05 seconds, backing up and moving on to the next if it hasn’t reached the desired one yet. This achieves a sort of rolling effect by which the final string appears on our screen over time. ...

April 11, 2011 · Ryan O'Neil

🐪 Reformed JAPHs: ROT13

Note: This post was updated to work with Python 3.12. It may not work with different versions. No series of JAPHs would be complete without ROT13. This is the example through which aspiring Perl programmers learn to use tr and its synonym y. In Perl the basic ROT13 JAPH starts as: $foo = 'whfg nabgure crey unpxre'; $foo =~ y/a-z/n-za-m/; print $foo; Python has nothing quite so elegant in its default namespace. However, this does give us the opportunity to explore a little used aspect of strings: the translate method. If we construct a dictionary of ordinals we can accomplish the same thing with a touch more effort. ...

April 6, 2011 · Ryan O'Neil

🐪 Reformed JAPHs: Ridiculous Anagram

Here’s the second in my reformed JAPH series. It takes an anagram of 'just another python hacker' and converts it prior to printing. It sorts the anagram by the indices of another string, in order of their associated characters. This is sort of like a pre-digested Schwartzian transform. x = 'upjohn tehran hectors katy' y = '1D0HG6JFO9P5ICKAM87B24NL3E' print(''.join(x[i] for i in sorted(range(len(x)), key=lambda p: y[p]))) Obfuscation consists mostly of using silly machinations to construct the string we use to sort the anagram. ...

April 3, 2011 · Ryan O'Neil

🐪 Reformed JAPHs: Alphabetic Indexing

Note: This post was edited for clarity. Many years ago, I was a Perl programmer. Then one day I became disillusioned at the progress of Perl 6 and decided to import this. This seems to be a fairly common story for Perl to Python converts. While I haven’t looked back much, there are a number of things I really miss about perl (lower case intentional). I miss having value types in a dynamic language, magical and ill-advised use of cryptocontext, and sometimes even pseudohashes because they were inexcusably weird. A language that supports so many ideas out of the box enables an extended learning curve that lasts for many years. “Perl itself is the game.” ...

April 1, 2011 · Ryan O'Neil

📈 Simulating GDP Growth

I hope you saw “China’s way to the top” on the Post’s website recently. It’s a very clear presentation of their statement and is certainly worth a look. So say you’re an economist and you actually do need to produce a realistic estimate of when China’s GDP surpasses that of the USA. Can you use such an approach? Not really. There are several simplifying assumptions the Post made that are perfectly reasonable. However, if the goal is an analytical output from a highly random system such as GDP growth, one should not assume the inputs are fixed. (I’m not saying I have any gripe with their interactive. This post has a different purpose.) ...

February 23, 2011 · Ryan O'Neil