frak: Transform collections of strings into regular expressions
github.com
github.com
At the moment I believe I have something that looks similar Figure 1, however, the algorithm is nothing to write home about. I wrote the initial version one afternoon and didn't do a tremendous amount of research regarding the problem. In fact, most of the commits I've made to the project have been to the README! I definitely would like to work towards something that more closely resembles Figure 2 and emit the most optimal regular expression possible. Naturally that means I would be rewriting most of it. :)
Again, thanks for sharing this.
I was working on a drop-in managed wrapper around re2[2] so .NET developers would have access to a good regex library, but damned if starting a company hasn't gotten in the way of finishing it. Still, re2 bindings are available for most other common platforms.
(Also I don't believe Java's regex engine is automata-based, which would explain the performance gains.)
1. http://fanf.livejournal.com/37166.html 2. http://code.google.com/p/re2/
https://github.com/danieldk/dictomaton
(It also supports perfect hashing automata and Levenshtein automata.)
In other news, how do you actually render an asterisk on HN?
Starting with v5.10, if Perl encounters a regexp that is just a list of strings, it will even use trie-based matching automatically.
Prior to that, people have been using modules such as Regexp::Trie to build optimized regexps and noted increases in performance similar to the benchmark shown in the post.
Learning regular expressions from strings is a fascinating but non-trivial problem.
If you do not have access to the Digital Library of ACM, scholar.google.com is your friend.
Vim uses an NFA style engine and it was obvious to me that backtracking with these patterns would be an issue. Since we went to such great lengths to provide the most accurate regular expression highlighting possible for Clojure, which is pretty damn accurate, I figured we might as well try to make it performant. It turns out our efforts were not in vain.
Have a look at this pull request: https://github.com/guns/vim-clojure-static/pull/28.
Sometimes, people have long list of strings that have total length more than 255 characters. frak would be a nice tool for compression.
It would be cool if the inputs weren't matched exactly, and frak could figure out a general pattern for your inputs (decimals, capitalized words, etc). That could help newcomers with a starting expression that matches their inputs.
Based on existing methods my solution started with the same trie and then generalised to a more flexible DFA by merging states. I used information theory (specifically Minimum Message Length) to turn it into an optimisation problem and tried a few different algorithms, in the addition of Ant Colony Optimisation to an existing algorithm produced the best results for my tests. (They were pretty limited, though.)
The problem is that there are an huge number of possible solutions for any given input. For example, you could always give a trivial solution: ".*"
For something like that to work, you'd need a large dictionary of common patterns, and then you'd want to compare against the dictionary to see if it matches a sequence of common patterns.
I can't imagine that sort of thing being too useful.
(Finding the actual minimal regex, instead of just a reasonable guess, might be a computationally tough problem. I guess it's in coNP and might be in NP, too. An algorithm in P would be nice to find.)
Update: Finding any separating regex would be in P. A separating finite automaton is easy to find, and then you just convert that into a regex. Now, how do you find the minimal regex?
preferably python but a link to theory is useful too.
I found my code and it wasn't exactly it (it just enumerated all regexes in order of size), but here's a crude solution now: https://github.com/darius/sketchbook/blob/master/regex/find_...
(In defense of my memory, I had written superoptimizers for other things.)
[1] http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.16.6...
You can rank candidates afterwards. However, it's a good solution for finding words that are closed to a mistyped word.
I have successfully used such techniques in a spellchecker and various search engines.
https://www.lri.fr/~hansen/proceedings/2012/GECCO/companion/...
Of course, you could generate two patterns; one with the words you do want to match and the other with words you don't. Then simply handle the logic in your program.
So this seems not to be the tool to auto-create a .gitignore file...
I certainly wouldn't stop at the output, but this is a very useful tool to speed up regex generation.