Wednesday, 31 January 2007

slow and stupid (6805 total)

I'm just being slow and stupid today, but I'm making progress, slowly starting to describe the local constraint stuff. Aaaaarrrrrgh. Also reread kinyon2000hbp and flipped through bits of bateman1997sgs.
$ wctex kowdraft.tex kowthese.tex 
kowdraft.tex (words: 525, pages: 3)
kowthese.tex (words: 6805, pages: 17)


The first count refers to the chapter I'm currently working on, the second is the whole dissertation.

Edit: Oh, and I forgot to mention, I broke the midnight barrier last night! Furious sleeping campaign here we come!

Tuesday, 30 January 2007

paper squishing

I can't believe this took all day (modulo kiloword, which takes approx 40 minutes). Turns out I was being stupid: was spending a lot of time trying to squish, when there's still bits and pieces to write anyway, obsessively squishing down to 10 pages when it really is just futile anyway. Feh.

Monday, 29 January 2007

slow

I wasn't really slacking off just being kind of slow. Something floating around in my head that isn't clear, but I'm not sure what it is yet. Try again tomorrow, I guess.

Heh, one bit of news. Turns out that I have been horribly miscounting my words. Turns out that the detex tool understands \input, which means that I've been more or less double-counting the thesis. So i'm not up to 13kw, just 7kw. Guess it doesn't really matter; just a relative word count anyway, but still...

Friday, 26 January 2007

job app done!

Yay! I'm really glad for this write-first mentality. Tying it to something "absolutely essential" like checking your email is a very good move because the rule permits no wiggle room. No kiloword, no mail. Well, ok there is some wiggle room now in that either it's 1 kiloword, or one highly-desired completed item (like the job application stuff). The only problem is that now when I come to the lab, my first reaction is "awwww maaaannnn, I have to write my stupid kiloword"; but once that's done, I'm happy.

So anyway, I managed to use a good chunk of the why-hire-me text from yesterday. I was a bit nervous about it because I kinda let my guard down and spoke more or less from the heart, presenting a semi-idealised version of myself, a sort of me as I understand or hope myself to be. But it seemed to work; both P and C think that it's pretty much good to go (although apparantly, the word "competent" sounds falsely modest. "Experienced", in my case, is much better because it's very objective and it says what I really meant to say).

The my-current-research stuff is also C approved, so with the two bits of text approved, I updated my CV, bundled everything into the Word file and sent it off. Done! One less source of stress; now I can focus on the chapter.

As for the chapter, heh... well, I've the admin stuff, updated my main latex and the Makefile, thrown in a few section headers, drew a rough mind map. Don't have much of an outline, not entirely sure what all the pieces are or how they should fit together. Planning to read more statistical stuff on C advice (because you can really think of it as a paraphrase selection mechanism). Kinda worried about the global constraints because we've been writing exclusively about the local ones. Also somewhat annoyed that I can't come up with examples naturally (guess will have to dig into our recent paper on that one).

I really shouldn't be so negative about writing. It can be a joyful experience when you produce something clear, when you figure out, "ah-hah! this is how you should explain it". I don't know... really hope I learn to overcome this hugh resistance to writing, learn to just do it, take pleasure in the process. Think of it as code maybe, but more creative.

Thursday, 25 January 2007

writewritewrite

Hey, I actually felt like I worked today.

Finished off half the job application, the bit that's asking me about my current research. Lots of cutting, write write write, oh shit that's way too long, delete delete delete. Useful exercise, gives me more clarity about what I'm doing, why I'm here, that kind of thing. I just hope I didn't say anything dumb. Will have to see what P thinks and then C. I'm also not sure how they wanted me to answer that question, details of my research and publications. Maybe they just want a list and bullet points? I dunno, I assumed the worst and wrote out actually paragraphs. Hate the process, like the results (increased clarity).

Now working on the information in support of my application part, the why hire Eric bit. Did I mention that I hate doing this? I don't really know what to say if it's worth saying something to the effect of "hey guys, I'm a coder, you want a coder?". I can talk about 10 years experience working on large software projects (define "large"), can list the languages actually used (C++, Tcl/Tk, Perl, Python, Java, Haskell)... is it ok to talk about the community stuff, the hobbies?

Meh, write write write, get it over with. Should be done by tomorrow right? First draft at least. Then I devote myself to cranking out my chapter.

Wednesday, 24 January 2007

write write cry

No I haven't started on my chapter yet. Now working on the job application, try to get this done well before 9 feb. The way I figure, it's the smallest of the two jobs and the most annoying (though not the hardest). I just want to get it done and off my mind, so I can focus on the task at hand.

I hate applying for things, writing the little letters or descriptions of me, etc... brings me back to when I was applying for undergrad. If I can get that over with, then I can focus on the chapter.

Have a minus-oneth draft of the "what are your research activities" block-o-text. Basically, it's an outline. There's lots of words in there, sort of descriptions, things I want to try out, a rough feel for what I'm going to be able to say and what not. Keep it short.

overgen

Had a small idea whilst building the minus-oneth draft: thing is that when you've got lots of sentences, it gets kinda tiring to figure out which ones are overgeneration and which are not (it doesn't always jump out at you like that, sometimes you can't tell whether you like the sentence or not, and multiply by 1000... ugh). So hey, maybe this is where the prob/stat guys come to the rescue. Can't we flag the least probable sentences as being likely candidates for scrutiny?

still freewriting

Still doing the freewriting-before-you-read-your-mail thing, not sure if it's useful yet, but I still believe that there is hope that this will one day transform me into an eric that's used to writing things on a regular basis. The current problem is that the freewriting is essentially crapwriting, whatever streams and flows out. But it is semi-handy to throw things out on screen, see what they look like when you attach real words to them. You know you'll have to kill 95% of it, but hey, if you get 5% of structure or 5% of clearer understanding of things out of it, why not? Only costs a little over a half hour for a kiloword anyway. Write to think, as wyd15-d says; write to think.

Problem with freewriting is that it starts to infect all your writing. Get used to writing in a certain way, drop a few pronouns here and there, censor yourself a little less, just churn churn churn.

Tuesday, 23 January 2007

squisher

I am Eric, Squisher of Papers. You just take all the tricks from high school and invert them. It's much better this way in the sense that in high school, you insert bullshit to create length. Here, you remove, remove, remove. Well... it helps to tweak a few examples, adjust a couple of vspaces, but I did also cut out some of my fluff.

Script-o-rama

Today consisted of increasingly frantic script hacking. I realised last night/this morning that I had some pretty serious logic bugs, was basically going about things the wrong way. You can't lump all the traces together, dummy, because then the traces from two different verbs (for instance) would merge together and you can't tell what's what. I really suffer a lot of boolean-inverse disease. It basically consists of (1) taking what what you want to do (2) writing down its exact opposite in code. Existentials, universals, takeWhile, dropWhile, lots of things like this. What makes this bad is when you have boolean-like situations within boolean-like situations, then you get inverses of inverses of inverses (and since they're not always the same kind, e.g. take vs drop, you don't get things nicely canceling out). Sigh. It's also why I can't write SQL queries (and why I will be doomed to a life of academia [hah! if I can make it at that]; this database moron is not to be let near your tables!)

See that's one thing with programming right... this is the thing the dynamically-typed language people say all the time: type checking won't solve all the bugs. For example, you can type check all you want, but you aren't going to save eric from boolean-inversion disease (/me shudders to think what type systems tricks you could come up with to deal with that)).

One scenario where I can imagine the dynamic typers having a point is if very tightly integrate your code with your editor (think SLIME)... if it became convenient to test in an absurdly incremental manner (write a bit, test test test test, write some more). There I could see the point, the argument being that the sheer immediacy of it helps you shake down bugs faster than type checking would. To convince me on this point, your super-cool environment would help me remember my tests in my code, and make it transparent to re-run them, store, them, etc. On the other hand, if you're coding in a dynamically typed language, and you're not using something cool like SLIME, that is, if you're programming like I do (one big block of code then run), I won't believe you. Also, if our environments also had cool features like compilation in the background (Xcode), and fancy ghci-text-editor integration, then the incremental testing argument would hold less water.

Anyway, I eventually worked it out: 283 lines of Haskell (dropping out the comments, of which there weren't many), a good chunk of it due to copy-and-paste programming.

and it's off!

The paper is submitted... now on to worry about the other deadlines. Chapter to write, chapter to write, chapter to write...

Monday, 22 January 2007

stupid day

A coding day today, but a stupid one, one of those annoying days where you try to do something simple and it takes you practically forever. I kept getting type errors... good thing too... because it turns out half my understanding of what I was doing was wrong, and I only got the picture once I looked at the types properly. Had to rewrite a bit of code, though to make it do the right thing. I'm basically just hunting down traces in test suites, but it's not entirely simple because I'm looking out for pairs of test cases in a single suite for which there are no differences in the traces... kind of situation I tend to deal with badly, these kinds of boolean inversion things, where you get your Trues and Falses mixed up, or your anys and your alls, or your nones and alls, etc. I dunno, just being stupid. The main issue is just really understanding in detail what it is you're trying to do. I got the big picture, can handle the details, but getting from big picture to details, that's tricky.

pairs...


Proof of my Haskell non-mastery... I wrote this piece of code and knew straight away that no, this is NOT Haskell-like. Haskell-like is when (1) there is practically nothing there (2) what little is there is obvious (maybe you have to learn a little Haskell first, but modulo learning Haskell, the ideal code is just immediately apparant, at least to the same extent as the task at hand). The task at hand is to have the cross product of a list with itself... well, half the cross product because you don't want to be redundant:
-- pairs [ a, b, c, d ] == [ (a,b), (a,c), (a,d), (b,c), (b,d), (c,d) ]
pairs :: [a] -> [(a,a)]


Here is the typical way too complicated erician version:
pairs xs = concat $ zipWith (\x ys -> [ (x,y) | y <- ys ]) xs (drop 1 $ tails xs)


Here is the first suggestion from #haskell (with an extra point thrown in for clarity)

pairs [] = []
pairs (x:xs) = map (\y -> (x,y)) xs ++ pairs xs


Apfelmus suggests
pairs xs = concatMap (uncurry zip) $ zip (map repeat xs) (tails $ tail xs)


And the nicest version so far, by glguy
pairs xs = [(a,b) | (a:as) <- tails xs, b <- as]


Yeah, ok, so I'm quibbling over one-or-two liners here, but is is clear that the alternatives proposed are much better as far as clarity goes. This is where programming gets nice, though, when it becomes Go-like. Easy to learn, hard to master.

Anyway, very pleased with the new pastebin (written in Haskell of course).

koan

A little Haskell koan for you... What does this do and why? It took me a while to get it, but when I did, I felt a tiny bit smarter...
filterM (\_ -> [False ..])
Funny, it made sense an hour ago... now I don't get it anymore [I know what it does, just don't know why anymore]. But it'll come back.

Saturday, 20 January 2007

so much for that idea

I came in here hoping to get some work done, catch up a little bit, but ended up spending the afternoon looking at Wikipedia (learning all about Unicode, the TRON encoding, etc) and otherwise just not working. Made a tree diagram, whoop-dee-do. Have some confusion about indices and nodes, but for some bizarre reason, GenI is segfaulting (segfaulting ?!) on C's machine. Something weird is going down; things working just fine up to now. I think this means it's time to go home.

Friday, 19 January 2007

braaaaaains

That would be zombie eric talking.

Hacking up the Makefile of Destitution (that sucker keeps getting bigger and bigger... now we're trying to support batch directories and all that jazz). I just realised that I had done something silly in the Makefile which makes it completely incapable of handling the case where the user is running several things in parallel <-- which happens. It shouldn't be hard to fix; there's just lots of jackhammering to do, dust flying everywhere. Makefile, Prolog, functional programming; like all things declarative, it's love, lots of love and a little bit of hate. The hate comes from the fact that sometimes you actually have to reason about things, whereas the love comes from knowing that you pretty much don't have any other choice. Get the feeling that this stuff blowing up is just it not hiding the ugly truth from you, but what do I know?

That Makefile hacking took a surprising amount time. I had actually found myself switching from one of my jobs to another, completely unrelated one. Thank darcs for cherry picking! It wasn't super-easy because some lines I didn't want to record were mixed in with stuff I wanted. Some spontaneous branching took care of that, though. Anyway, now I've got a pretty big bug in there that I want to fix, that crazy parallelism stuff... but have to do some digging.

I can't remember what I've been doing; it doesn't seem like actualyl that much, but I'm not sure. Maybe just inefficient. Spent quite some time working out the logic for clumping a bunch of data points together at increments. Feel dumb... seems like it should be easy, but I end up getting something that looks like this:

> rawPoints = someListOfNumbers -- [ 1, 7, 8, 9, 4, 4, 13, 5, 8, .. ]
> xTics = takeWhile (<= cutoff) $ iterate (+ incr) 0 -- [ 0, 5, 10, 15, .. ]

> points = pointsFor rawPoints xTics -- [ (0,3), (5,4), (10, 1) ]
> pointsFor ps ts = reverse $ pointsForH ps (reverse ts)
> pointsForH ps [] = [(0, length ps)]
> pointsForH ps (t:ts) = point : pointsForH smaller ts
> where point = (t, length bigger)
> (bigger, smaller) = partition (> t) ps

Thursday, 18 January 2007

misc stuff

freewriting

Hey, I think I'm liking the freewriting thing. This time I actually wrote about work related stuff, although in the same mental dump format, don't think, just purge. And what came out of it is a bunch of questions on yang1991ffs. Questions are good in that they are a whole lot more precise than my general HUH? Questions are a recipe; they say, if you can answer me, maybe you'll understand how it all fits. Another reason I'm happy with it is that I actually found the way to explain what had confused me about SFG all this time. (This might sound similar to yesterday).

The confusion behind SFG is that there are two kinds of parallelism: parallel networks, and parallel traversals. What's nice about this is that it also accounts for my many other confusions. You can make a table showing
parallel networksparallel traversals
hierarchy of choice points
hierarchy of regions
conjuction/disjunction
conflation


The other thing that helps me is to try and translate things into some language I know better:

type NodeName = String

data Region
{ tagTree :: Tree N
, mappingTable :: Map Ikkiwubble NodeName
, functionalRoot :: NodeName
, conflationSet :: [[Ikkiwubble]] -- ^ self explanatory
, expansionTable :: Map Ikkiwubble Region
, unrealisedFeatures :: [(String,String)] -- ^ not sure about this
, subRegions :: [Region]
}


(Oh yeah, ikkiwubble instead of ixiwubble; it's just easier to say)

I guess my main issue now is figuring out exactly what happens when you hit a preselect operator. How do you know what part of the input specification the ikkiwubble (function), say agent corresponds to? One guess is that if you look at the input specification as a recursive feature structure, then an ikkiwubble simply corresponds to one of the features (really simple).

I was also initially confused about the idea that there is an hierarchy of regions, but then I found an analogy which made it all make sense. You know how you're writing a program, and you call fork() to spawn a new process? The new process is the child of the parent process, right? There ya go, instant hierarchy. Yes, you can have an hierarchy of parallel traversals. Reconciling the idea of parallel with hierarchical isn't hard after all.

Oh well... I still don't get it yet. I dunno, maybe I shouldn't be going too deeply into this. It's just annoying because now you actually have enough meat to work with; there is enough material for you to actually understand what's going on. Hmm... actually, maybe I should just wait for his PhD thesis to arrive. Maybe that will lay it out all nice and slow.

category theory

Attended a short course on category theory. There's two more sessions to go. I dunno... I'm just here as a random Haskell programmer, trying to see what this could do to make me a better programmer. So we've got a reeeeaaaally abstract thing that generalises over a bunch of less abstract stuff. But being a non-math guy, I don't even know what these less abstract things are, so is there a point? But maybe this would give me sort of a top-down view on things... maybe it'd be like speaking Esperanto as your mother tongue?

hunting for overgeneration

Had a discussion with C on hunting for overgeneration. Yeah, the programming and the fun let's-hash-some-ideas-out-on-the-whiteboard thing; these would be the high points. Reading and writing, basically the low ones. However, understanding something that you've been reading on and off for two years and FINALLY getting it, that's a mega high point.

Wednesday, 17 January 2007

yang1991ffs

Alright, I basically spent the whole day trying to read yang1991ffs. It was tough in the beginning because I kept wanting to something else, anything but read, but after a few hours of just being stupid I finally managed to coax myself into it. This article is a bit longer than the other two I've read in this series, which is good because they can afford to put a bit more meat on their technical bone. Indeed, if ever there was a text that would help me to "get" SFG, this might be the one. My head is still kinda swimming from trying to understand what's going on, but here we go:

SFG in my terms

The thing that makes SFG confusing for newbie eric is that there different kinds of "decomposition". I have a hard time telling them apart, or even knowing if they are genuinely different. As I understand it now, there are three kinds: the network hierarchy, conjunction/disjunction of networks, decomposition of the input specification, and rank-wise decomposition (?!). Oh wait, the last two are the same thing.

The other thing is that SFG throws around the word "function" alot -- this is just me being stupid -- whereas for a functional programmer like me, that word triggers all sorts of irrelevant associations. (Although AR seems to say something about representing Functions in the SFG sense with functions in the FP sense). So let's say we don't like the word function; let's call it something else like "purpose" or "ixiwubble". Ayup, SIL, Systemic Ixiwubblistic Linguistics.

decomposition of input specification

So here's the new thing I learned about today: rank-wise decomposition of the input specification. Ditch the rank-wise, for now; don't really know what it means. The big deal here is that when you're traversing the network, you sometimes hit a certain trigger (PRESELECT) which causes part of the input specification to be cut out and realised completely independently of what you're actually doing. In programmer terms, the thing spawns a new thread and now you got two network traversals going on in parallel. The big secret is that the new thread consists of re-entering the network! It's a recursive call: traverse net foo(bar) = traverse net bar ++ bunch of other crap

So what? Well, it means my mental model of SFG has been all wrong. I somehow thought there was ONE network traversal but different things going on in parallel, right? I somehow imagine that the whole input was just there as a resource, that gets consulted whenever one piece of network wants to know something. But nope, it's not like that. That sounds soooo similar, but it's not the same thing. What we got here is decomposition of the input specification, and a whole separate traversal. In fact, you start over! (Actually, the PRESELECT operator can make it so that you start from a specific point in the network, but in order to get what's going, it really helps to just think of this being a whole new traversal starting out in a separate thread).

SFG vs TAG

This paper explains why SFG wants TAG (and why TAG wants SFG) in terms that stupid programmer/engineer eric can understand, sort of. It's really like trying to clean up a computer program: you've got a big messy SFG grammar that's trying to do too many things. It's trying to represent how ixiwubbles (functions) relate to each other, and it's trying to say enough things about syntax so that you don't get output like "Who Mary John love did?". A better way to do it is strip all that syntax crap out of your SFG and just talk ixiwubbles, ixiwubbles and only ixiwubbles.

pick this up later

Aww man I'm too tired for this. I'm just going to go home and talk about this in my free-writing exercise tomorrow. WYD 15 min/day suggests that I try to get into a habit of (1) writing every day (2) writing first. Like, literally first. The desired outcome is that from now on, the first thing I do whenever I get to the lab is write 1000 words. Like really first: remove your jacket, sit down, write 1000 words. The reward for which is that I get to check my email.

For now we focus on regularity, not on content or on quality. 1000 words of anything, as long as it's the very first thing I do. What should hopefully happen is that after a while, it just gets easier to associate go-to-lab with write-1000-words (ding ding ding! salivate...). Once we've established this habit, we start increasing the roughage: slowly turn up the dial on the structure and focus (i.e. write about work stuff, instead of whatever random crap just passes through my head). But the important thing is crank ze words out.

I realise that koweynlg means that I already spend lots of time 'writing' (especially writing crap). The two key differences are that (1) this one is first thing in the morning (2) this is eventually going to be my thesis-writing time.

Tuesday, 16 January 2007

misc

make run-batch SUITE=all

Added a new feature to the Makefile-of-Deprivation: the ability to run a directory-full of test suites. This is one thing semconst has been able to do for a long time, but which I never bothered to implement. But now that we have a clear need for it...

  1. put all dyalog-output in suite/semconst-output
  2. make run-validator SUITE=foo
        (re)runs the validator for a specific suite. Do this for each suite. Optional, but probably more comfortable this way.

  3. make run-batch SUITE=all
        validates and geni-converts all semconst suites; combines the resulting geni suites into one file (*.geni-input => all.geni-input) and works from that one file. By virtue of Makefile dependency tracking, this detects if you have already run the validator, so don't worry about any redundant steps taking place. Also, if you ever make a mistake in validation, you can just re-run the step above to correct a specific file and then re-run this step.


Well, it's a bit of a hack, and it isn't smart enough, say, to use the all grammar when you're just trying to run a single suite. I could that functionality in too, but only if it's really useful, because it's just more intelligence/complexity to throw into the mix.

yang1991ffs

Trying to read this article now. Should hopefully give us more details on the systemic TAG stuff.

active projects

  • Papers with C - 23 jan
  • paraphrase selection chapter - 15 feb
  • applying for a job - 20 feb
  • Adjunction polarities implementation


adjunction polarities probably play nice with intervals


I was talking to the good folk at Clgrm yesterday. They say that they use a similar idea to our adj-as-multiplication for dealing with coordination, which is interesting, except that I don't really know what they mean. In other news, Clgrm's doing some fun stuff with their polarities for parsing. I'm not sure if they've written up about it yet, so I guess I should keep the blogging on a leash.

Also, I was a bit worried about whether it would be practical to implement the multiplication scheme given intervals (atomic disjunction)... but then it occurred to me after coffee that intervals don't really matter. Look, the intervals you're going to get for adjunction polarities are ALWAYS going to be zero to one. So who cares? When you multiply them together, the worst that can happen is that you go from a zero-to-one interval to... a zero-to-one interval.

yesterday

In our discussion, it came up that I should consider looking into ACG and see if there is any connection with the systemic stuff (eh?!). Thanks for the thought!

what next


Tidied up and pushed in all my changes on the polarity and the trace filter stuff. It should just work, but I'll have to run it chez C to be sure.

I'm really tempted to work on those adjunction polarities right now. I'm a bit worried because there's two layers of polarities to deal with (abstract-data-type, anybody?). And I'm not convinced that we have our indices in the right place, but that's a seperate issue. But now that the intervals thing is taken care of, I feel like we're ready to go ahead.

writing your dissertation...


I'm really impressed by our Centre de Documentation: they always manage to find what I need, fast and friendly for that matter. They've also completed my suggestion to purchase Writing Your Dissertation in Fifteen Minutes a Day by Joan Bolker, now in my grubby little hands. I don't know how useful it's going to be. Maybe it's going to be cheesy self-help. Or maybe it's going to be The GTD of PhD students. Will have to see.

Monday, 15 January 2007

visitor and code

Showed GenI to Aarne Rante today. I didn't prepare it as well as I should have, so I hope I didn't waste too much of his time. Also got a little glimpse of GF in his talk. Speaking as a programmer, the whole type-checking thing seems like a good idea. I dunno. I guess the whole IANAL applies here, where L = linguist.

Other than that...

Worked on making the derivation/trace output easier for C to pick up. With the current version of GenI/Makefile-of-Dervishes we now get in in the geni-validated file, which *ought* to be convenient enough for regular use.

Had itchy fingers, so I couldn't resist working on the morphology some more. It was just a quick hack. I know I have better things to do, but I wanted to make it so that we could return all the morph variants instead of just picking one. We won't be able to play with it for a while maybe, but it's nice to know it's there, so that if ever there is a null, we can make our inflections come out reasonable-like.

Itchy fingers. I can't find it in a google of English idioms. What is that? A Malaysian English thing? British? It's from my youth; that's all I know. I like that expression. It means a sort of inability to control one's meddlesomeness, inability to leave well enough alone, tendency to interfere in crap where you got no business interfering. Something like that. Somebody want to give a better definition? Urban dictionary has some totally unrelated meaning to the one I was scolded for having.

Friday, 12 January 2007

one kilopatch

The GenI repository is now 1000 patches long. (Admittedly the last three patches were documentation and homepage tweaks, because [1] I felt like cleaning stuff up [2] I wanted to push the counter over).

Corrected some minor annoyances today. The display of derivation trees was broken because the node names had ':' in them, so I wrote a little mungy filter to make graphviz happy. Calls to viewtag were similarly broken. I guess this is what I get for using String to store tree ids, instead of using a tuple of String, or something more strongly typed. Type check now or suffer bugs later.

half-hearted reading


Not very productive otherwise (sigh) despite 12 hours of sleep to make up for yesterday's all-nighter (hah! I had set my alarm for 06:30 in the hopes of bouncing back into taking-things-seriously-eric).

Talked to the folks at the CDD about obtaining some articles by Yang, SFG and TAG stuff, maybe even his PhD thesis.

Tried half-heartedly to learn about parsing techniques for SFG and MTT.

Not sure what to make of the MTT stuff (nasr1999gap), which proposes a "generative formalism in the framework of MTT" and a parsing algorithm to go with it. The article claims that the resulting grammar is not very practical to write by hand (lots of redundancy) and suggests compiling from a standard linguist-friendly MTM (I dunno, what's that, the standard way of writing MTT grammars?) to their formalism. Is this something that's theoretically possible and nobody's gotten around to working out the details? Or is this the kind of thing you'd need to explore to even see if it's doable? Also, could the formalism they propose be used for generation, or would we be better off with a standard MTM? The paper says that working on the compiler will "clarify the relation existing between the piece of work described in this paper and the MTT". Oh... so that's not quite reversibility either, is it?

Don't see anything for FUF, except this article talking about implementing HPSG in FUF (matiasek1995ihf) That doesn't really sound like what we have in mind, because if you're just using it for that you're not exactly doing all that system network stuff, are you? The other two articles I downloaded, (kasper1998eps, bateman1992nrs) seem to be a bit more promising.

sigh

I've got the not-working-hard-enough blues. Let's see whether I can snap out of it next week. One could describe this as an over two month long funk, starting when I went home chez my parents and found myself basically not working (despite ample opportunity, and time to myself with nothing better to do) and stretching out across the month of December and spilling over to January. Com'on eric. Kick into gear already. Being in gear feels great, nothing at all like this business of trudging through your days. In gear is "hurry up and shower so we can get to the lab", whereas the present state of mind is "don't... wanna... move..."

What's on my plate is essentially:
  1. Help out with the articles
  2. Write my paraphrase selection chapter
  3. Implement polarities for adjunction and indices
Coder-eric would much rather work on #3. The half-hearted reading attempts were sort of for #1. But I guess what I ought to do is start on #2.

Thursday, 11 January 2007

morphahuh?

Ok, I guess I've figured out some of the morph issues: one of which is a zip-with-mismatched-lists issue, where you have two lists that you're really expecting to be the same length and you zip them together. Mere zipping doesn't capture this requirement, though. You have to explicitly use a zip (or zipWith) that matches these lengths (for example, one that has an undefined when the patterns doen't quite match). Case here is that I have a list of input sentences [String], and I want to return a list of output sentences [String]. I never express anywhere that there should be exactly one output sentences for every string, but in fact (to my surprise), I am because I'm zipping them back together at some stage. Leads to well-typed, but very unpredictable results like "whhaaat? why am I missing half of outputs?" I suppose the correct approach to this would be either to (1) express the length-match requirement in the type system (2) at least be undefined when there is a match. Blowing up sucks, but it's better than doing something unexpected.

Ambiguity, ambiguity. I've taken up a notational convention to deal with ambiguity. When there are two many results for a single lemma, I do not return all of them. Instead, I return the lemma annotated with a '*' to indicate that this one was way too ambiguous, most likely indicating that something had gone wrong. Similarly, if there are no matches in the morph lexicon, I return a lemma with a '-' tacked on to it.

Sooooo tired. Goofed off all night on the net, so got maybe a couple hours sleep. Took me till 15:30 to leave the house. Guess I'll have to make it up by coming to the lab on the weekend. Sigh. I dunno. Maybe this is my chance to deliver the decisive blow, maybe this is time we upgrade from the aggressive sleeping campaign to the radical sleeping campaign. Hard reset?

Wednesday, 10 January 2007

morphology semi-done

pre-terminals

I was trying to (re)-implement the morphology stuff, basically modify GenI so that we read feature structures off the pre-terminal nodes instead of the terminals. One problem is that I had always assumed (and so had CA) that you just replace/unify the lexeme with the anchor node. Only much later (bugs later) did I learn from YP that in fact, you do not unify/replace the anchor, but you attach something on to it.

The first worry was what exactly we mean by pre-terminal. A node above a terminal node, right? What if it's above TWO terminal nodes? (Maybe you only notice these things if you're actually trying to write the pattern-matching code?) What if it's above a terminal node and a non-terminal one? You could argue, I guess that such cases never occur in TAG, but (1) i don't really know that (2) even if it didn't... yeck! who wants to have walk around with ticking timebombs in their code? Anyway, this turned out to be not so hard to resolve. You just associate the same pre-terminal node with each one of its children (maybe I'm going to regret this):

> -- | Return pairs of (parent, terminal)
> preTerminals :: Tree a -> [(a,a)]
> preTerminals (Node _ []) = []
> preTerminals (Node x ks) =
> [ (x,y) | (Node y ys) <- ks, null ys ]
> ++ concatMap preTerminals ks


Now the "fun" part. The next obstacle is that I tried to make the "simple" builder faster/simpler by only using node names for building the derived trees. You don't actually need the feature structures for that; it's a separate layer of control. When you're unifying the feature structures, you don't actually care about the structure. Problem is what happens when you want to return the results. I solve this by putting in a structure that maps node names to back to lexemes and to features structures, but only for the leaves. But that's wrong! That's wrong because the features you want to return for morphology are not leaf features but pre-terminal features (aaaaaaghhh!). Ok, at first I thought you had to modify adjunction and rename any preterminals that received adjunction. But that's just wrong; splicing is saner than that. So no big deal: just tell the builder code to track preterminals instead of leaves. Took me a while to figure out, though.

morphology stuff

Anyway, now that the pre-terminals stuff is taken care of, la morphologie remarche... it's working again. It used to be broken because the morphological post-processors were always getting empty fs on input, but that was because of the old assumption that we were using terminal nodes.

I have also implemented a small in-house morph post-processor. It is dead stupid. It just finds the first thing that the lemma and fs unifies with. But it should be good enough for our needs. Implementing this stuff was super-easy wrt to worrying about pre-terminals and all those gut things. Most of the time was spent refactoring the parser code, and trying to document things as I go along.

The result?

Eh, not so hot. Edit: to be more precise, it sucks. Mucho ambiguity I spent a couple minutes puzzling over the thing, trying to figure out why we didn't have any results. Turns out it was because the morph lexicon calls part of speech "pos", whereas we call it "cat". There might be a technical reason for this. I don't care.

Anyway, it works (sorta). No more "jean aimer marie", but bona fide "jean aime marie". I've got it returning all matches from the morph lexicon, so you get a little combinatorial burp. This exercise makes it pretty obvious why you want a proper morph generator instead of just looking things up in a table.

doc/manual

I know I've already said this, but I'm feeling slightly more commited to the idea now. I think I'm eventually going to push for a darcs-style manual, where the source code comments are the user's manual. This means re-writing a good bit of the comments so that they actually make sense to somebody who's not looking at the code, but going in this direction should improve both the user doc and the code doc. Anyway, what the user gets in the end is a PDF, so s/he shouldn't even have to know that they are source code comments.

Tuesday, 9 January 2007

derivations and traces

The fun days are the ones where you just sit down and code. (Does this make me more ingénieur than chercheur?). I guess it depends what kind of coding job you have. Here I actually (1) am interested in the product itself (2) get to use the tools I like the best [a language that lets me put thought to code, instead of boilerplate to more boilerplate] (3) have the luxury of continuous refinement as opposed to the real-world pressures of ship ship ship. It's great fun, a creative activity, problem solving, fluidity, blah blah blah.

I finished the implementation of the derivation and traces stuff today. Now that infrastructure was in place, I just had to write the code that plugged the derivations in, and the code that saved them into a file.

A large chunk of the time was spent cleaning out old code, simplifying it, improving the documentation. Every time I pass over an old piece of code that I want to extend, my first reaction is "yuck! you wrote that?". So I feel obliged to clean it up: refactor, twiddle, simplify. First, clean it up, and then insert the feature. It's usually motivated by the realisation that the feature I'm going to insert is kinda similar to the pre-existing code. I just abhor copy-and-paste coding... the whole idea of it, gah! The best patches are the ones that remove more lines than they add. The approach is very bottom-up. No plans, just code, refactor, refactor, twiddle, tidy, refactor, code. I just don't have the mental discipline to plan things out. Just sorta implement according to unspoken master plan, a mental representation en gros what ya gotta do. I don't advocate this as the right approach to programming. It is just how I've always done things, despite summer schools insisting I do my VB top-down, despite the project planning classes from Uni (Mythical Man Month insights, etc)... stubborn refusal to plan. I hope this mix of obessiveness and attention-deficit undiscipline won't be too much of a handicap me when I stumble out into the Real World. Is it worth hiring a programmer who spends half of his time rewriting things? Who fiddles with the colours (*) on his literate Haskell PDF that nobody's going to read anyway? (It's still pretty crap; more literal than literate).

Tomorrow, morphology. Just spend one day on it, get it done and stop spending your PhD wishing that GenI does it.


(*) I was thinking that if I made the code gray, it would be easier to visually distinguish between code and text. Blue is a bit extreme; I don't want to kill people's colour printers.

Monday, 8 January 2007

texhacking and a little haskell

Spent this afternoon (still not doing a good job on the whole early-to-bed thing) tweaking BibTeX and LaTeX stuff. It's the kind of job that has the potential to become mindless if you don't pay attention. Useful to pay attentiot to decisions like "well, is this cite more appropriate, or that one? If I cut space consumption this way, will the article stop making sense?" Anyway, glad that first chunk is over with.

Handy tip for finding bibtex errors (kowey-generic users), hunt for "database":
make 2> /dev/null | grep database


Now breaking ground on the derivation output code. Now instead of outputting sentences, I want to output sentences and their derivation. So I have to change (1) the builders (2) the builder interface (3) geni calling the builders (4) the user interface, the whole vertical chain. This kind of work makes me glad for strong/static typing. Sure you try to pay attention, but having the compiler there just telling you "ah no, you missed a spot"... that's very reassuring. It's much better than coding it up, testing it out, and watching it fall on its face (lather, rinse, repeat). The macho programmer might say something like "oh, well if it falls on its face, it's my own fault for not paying attention", but me, I'd rather have the smug annoying friend telling me that I'm headed for disaster, forcing me to get it right before I even think about running that thing.

Friday, 5 January 2007

growl and grumble

The aggressive sleeping campaign must have been a little too aggressive lately. Getting up was hard. Got here around lunch, nine hours of sleep later, tired as hell. My body totally confused, artificial jetlag. I suspect that's been putting me in the grouchy mood I've been in all day.

This morning in bed I was worrying about SemConst. I realised that my plan to switch intelligence over to the Makefile had a crucial drawback, in that in SemConst-land, recompiling things is a feature, not a bug. The problem is that modification dates are not informative enough in a setting where you've got fully parameterisable input. Say I've got two grammars, Old and New. If I run SemConst on New and then run SemConst on Old, I will have introduced a subtle bug. Things don't get recompiled, even if they should, because, welp, Old's modification date is earlier. Grumble grumble grumble. So I had to rethink the plan.

This is a non-issue in the Makefile of Death because you can't parameterise anything with it. Hah! Take that, user friendliness! Soon I'll be forcing everyone I work with to use vi! AHAHAHAHAH

Err... sorry. Actually, yes you can parameterise things. There is limited parameterisablility in that (1) you can pass in the suite name you want to run via a makefile variable (make run SUITE=Verbs) (2) you can edit the makefile if you want to use a different grammar or something. The essential difference is that Makefile of Despoilation land is a closed system, so everything just works. Solving different problems, we are.

The revised plan is to continue to push intelligence into the semconst Makefile and just invoke it directly from the Makefile of Distraction. It doesn't care about parameterisability, so that should be ok. The SemConst stuff will just have to continue systematically recompiling things. It will have to systematically run make clean to make sure things happen. Complain complain. I could continue working on this, but it's a pain, and I'm not sure it's really worth it. We'll just have to recompile things for now, unless I get some sudden inspiration or something

Shifting focus to GenI. Need GenI to start producing those derivation trees on output.

Thursday, 4 January 2007

zommmmbieeee

The aggressive sleeping campaign takes an usual turn today as Y leaves for Germany and b224 have an early bon-voyage breakfast with him. In other words, somebody here writing a blog didn't get much sleep last night and is somewhat zombified.

After running around in circles doing stupid Haskell tricks, I modified the plot-generating script to produce nice output in a completely automated fashion. No need to tweak axes or anything like because the ranges are calculated automatically from the data points. I also modified the Makefile of Derangement so that when you do
make count-paraphrases SUITE=verbs
you get a suite/geni-paraphrases/verbs-num-paraphrases.pdf with an autogenerated plot.

That's about it. Today took a pretty strong productivity hit.

Next step is to fix that SemConst loop so we can do parse-gen. Then I see if there is anything I should contribute to the article. Then we have a chapter to write.

learning things

That being said, on #haskell today, I learned a new trick for doing flags a switches. Just use a record and some anonymous functions for GetOpt. I'm keeping the old code though, because setFlag is still somewhat convenient to have (I suspect that the list of flags way makes more sense when you have a looooooooooot of flags), but you have to admit that being able to the flags stuff without any crazy existential types or Typeable or yucky stuff like that is very nice. So, thanks, kosmikus for the simple solution.

Another thing I learned today was talking with S: I was wondering about typing and function pointers in C. It turns out you can have some pretty good typing on your function pointers (hey, this is vague for me nowadays). You can type the arguments your pointed-to function expects and the kind of things it returns. The two places where functional programming makes life easier wrt higher order functions is (1) partial application (2) anonymous functions. Anonymous functions are a pretty big deal too. For example, what if you want to return a function as a result? With anonymous functions, it can be one that you make up on the spot. Good to get a clearer picture for this. Higher order functions make life so much easier. Having good support for them is nice... and now I have a better sense for what kind of support, say Haskell, gives me as opposed to, say C.

Wednesday, 3 January 2007

the walls have eyes

So it seems C is reading this blog (heya), or at least skimmed it on occasion. Well, good. I've been writing this from the beginning with the assumption than anyone could be reading at anytime, so mission accomplished, objective: total transparency. Koweynlg started out of a general sense of frustration. I never seemed to know where all my time went. Keeping a private journal wouldn't cut it because I would eventually get bored and just stop. Keeping a public daily journal, that's much better for accountability. It's easier to imagine you have an audience (yeah... right).

Keeping it honest is suprisingly easy. I have no qualms about saying that I spent an entire week slacking off, audience or no audience. Un, I'm really bad at lying, some kind of genetic mishap, social handicap if you will. Deux, it is ultimately my problem if the thesis don't get done, and therefore push comes the shove, the only person that gives a shit if I work or not is me. Trois, the blog is mostly for my personal needs, it functions as a diary, and nothing is worse than lying to your future self. Quatre: writing this blog has become a force of habit, a semi-automatic process, getting ready to leave work? Core dump. Qu'on vide son sac. And here's the trick: after a week of saying you've been slacking off, knowing that everybody is reading about slacking off, you start to get a little self-conscious and getting back to work. It goes a little like this:
Honesty + Blog --> Accountability --> Productivity

That being said, today I got a friendly and well deserved reminder that I've got a paraphrase selection chapter to write... yeah... just one more script and makefile hack, eh? But yes, that is the entire point. Koweynlg exists to keep me honest, and to keep me on my toes. I'm sure it's not as simple as that. I've probably spent months whining about my lack of productivity with nary a result. But I like the feeling of it. I like the very thought of working in the open, my faults and failures ready for all to see.

Makefile of Drama

Tweaked the reporting from the Makefile of Despair. Trying to work our way to a more meaningful naming scheme.

SEMCONST stuff

I showed off my My-First-Oz-Code patch to Y today and he seemed to approve. Also learned that the curly braces has nothing to do with the distinction between statements and expressions. Ok, just method invocation for objects (for classes, you would use parentheses). We agreed that in order to avoid re-compiling the grammar each time C ran it in batch mode, we would have to move some more of semconst's intelligence into the Makefile (it's either that or compare dates, booorrring). Looks like I have a bit of hacking ahead of me, just a bit, just enough to get it so that we don't have to keep re-compiling grammars, and so that GenI can share the semconst grammar.

GenI stuff

I didn't really mean to do this, but I couldn't resist. I cleaned a bit of the enrichement and co-anchors code so that it would be easier to print out warnings without using unsafePerformIO. The trick behind all this is that you really do NOT need to mix IO or State into your code, not always. Sometimes, it's just a matter of cutting your functions into smaller pieces. Instead of one monolithic function which spits out unsafePerformIOs given a certain condition, I now have two functions: one to do the work, and another to check for warning conditions. You might have to refactor so that the two functions share common code, but generally, the right solution to the oh-no-Haskell-is-too-pure problem consists of making your code cleaner, not introducing another hack.

Paraphrase counter

This took no time at all. Remember how skeptical I was about extending the GenI parser, and making everything go through the parser? It was the right decision after all. Making little scripts to deal with this crap is pretty trivial. Just call the geniparser and extract values. I ought to go back and learn how to make a library with Cabal. Instead of distributing all these scripts with GenI, I could just make a libgeni and write the scripts anywhere. Here's what the script looks like (click to enlarge):

Tuesday, 2 January 2007

stumble grumble

I promised that 2007, we get back to business. Well, let's call it a transition day: I officially start my aggressive sleeping campaign tonight, pushing back from a 07:00 bedtime (a bit on the nocturnal side) to a more reasonable 22:00 (hoo-ah!). Got in around 13:30, Happy Meal (TM) in hand and very much not ready to work. There's nothing I find more amusing than walking to the lab carrying a Happy Meal. I wish I was dressed in a suit and tie and carrying a briefcase at the same time, reading something important looking, like the Financial Times. It would be a three way contrast. A lab researcher dressed in a suit, carrying an Happy Meal.

I was pretty tired this afternoon. Spent quite a few hours avoiding work, probably the most useful thing I did during this period being to learn that Evaluating cellular automata is comonadic (sigfpe is really good at making scary-looking stuff accessible to the yellow belt Haskeller). This might or might not have any actual use for my PhD. You could argue that learning about zippers is useful if you want to be a tree-jockey, and this post slips as bonus-value as slightly strong grasp of what zippers are. The reality is that I was just avoiding work, just zoning out.

I finally got down to it around 16:00 or so. I opened up the Oz code to SemConst and went "gah!", not because of SemConst, but because of the syntax highlighting. It turns out that you just need fiddle the oz.vim script a bit -- I removed the hard-coded colours, twiddled some of the regular expressions and pruned the syntax highlighting down to something a little gentler. Yes, colours convey information, but too much information and brain shuts down.

Then I set myself to thinking about how we could achive the twin goals of
  1. Being able to run the parsing-semantic construction tool chain more than once without recompiling the grammar (maybe this is possible and we just don't know how)
  2. Sharing a grammar between SemConst and GenI
We're definitely using SemConst's grammar-cutter because the cutting is based on sentences, and not semantics. I think we should break the chain down into two discreet steps - build the grammar, parse with the grammar. It would be great if we could do it in a way that is friendly to my mother-of-all-Makefiles (which combined with gtester, seems to do the same thing as SemConst, sans graphical interface). A bunch of stupid technical crap, this is, stuff we shouldn't be wasting our time on. Oh well. I guess thinking about this crap saves us from having to do any real thinking, heaven forbid a Phd student might want to think.

Does anybody ever read-by-coding? I was trying to understand how the toolchain works, but then I noticed some apparant redundancy, so I built my first ever method in Oz:

meth systemMaybeVerbose(V)
local
S = {VirtualString.toString V}
in
if @verbose then {System.showInfo S} end
{OS.system S _}
end
end
I'm not sure I understand all of it, like the difference between == and <- (I'm guessing the first one is unification and the second is affectation, but does that even make any sense?), or why some things need to have curly braces and others don't. Apparantly, Oz is one of those languages that actively distinguishes between a statement and an expression (ya know, that sounds just like actions and expressions... monads?), yet I don't see why something like VirtualString.toString or List.foldR would be enclosed in curly braces. Wouldn't these just be expressions? Then again, maybe it's to allow for things being toString-ed or being folded to be impure. Anyway, so here's your method, now buy it! (I hope Y likes the method; we'll see what he thinks tomorrow)