From: James Edward Gray II Date: 2007-06-07T07:02:07+09:00 Subject: Re: Gecode/R - Request for syntax feedback On Jun 6, 2007, at 12:35 PM, Andreas Launila wrote: > If I understood the suggestion of the syntax correctly then > constraints > would basically be given on the form "constrain > variable.predicate(argument)" when variable is a single (finite- > domain) > variable and "constrain function(variable).predicate(argument)" when > variable is something enumerable. > > I have written down some examples of how constraints could look with > that syntax at http://gecoder.lokorin.org/dev/wiki/Syntax_test . There > are some constraints there which I couldn't get especially readable or > self-evident. I will go through them below. I'm liking this direction, for what it's worth. I'm worried about the ones that require changes to core classes though and I think we generally want to avoid that. That may be an argument for the earlier proposed variable(), since it could wrap the data structures in proxy objects supporting the extra calls. Random thoughts from that page: * We probably shouldn't use sort(), because a class my inherit a sort () from Enumerable. * Could all_equal() be same()? I was just wondering if that paired better with distinct(). I don't hate all_equal() though. Just a thought. > == Element constraints == > > This is basically the array access of constraints. It takes an > array of > constant integers, selects the i:th one where i is decided by a > variable, and constrains that variable to be equal to another > variable. > This can typically be used to convert e.g. an identifier to a quantity > of some sort, for instance the price of a fruit. > > A short example: > > fruit_selection = IntVar.new(0..3) # We can pick one of four fruits. > prices = [45, 60, 764, 45] # The prices of each fruit. > price_to_pay = IntVar.new((prices.min)..(prices.max)) Could this line also be: price_to_pay = IntVar.new(*prices) ? Just curious as it made more sense to me that way. > constrain prices[fruit_selection].equal(price_to_pay) > constrain price_to_pay > 500 > > The above example will force fruit_selection to equal 2 (no branching > required) since it's the only fruit with a price > 500. > > I would imagine the above syntax of "constrain array[x].equal(y)" > to be > easily understandable, but it would require modification to Enumerable > to define/wrap []. The []() method is defined in Array, actually. > Something more on the form of the rest of the syntax > would probably be > > constrain element(array, x).equal(y) > > It just doesn't read as well to me. Maybe there's a better way of > representing constraints where the function has to take multiple > arguments, such as returning an helper with only one method, i.e. as > follows. > > constrain element(x).in(array).equal(y) I would say avoiding core class modification is important. If that means we need element(), that's probably just a price we need to pay, in my opinion. See my earlier comment about proxy objects for another option though. > == Channel constraints == > The best syntax I can think of for it is. > > constrain channel(xs, ys) > > That is probably because I can't think of any common concept that > conveys the intention in a few words. Looks reasonable to me, at least as far as I understood this one. ;) > == Sort constraints == > > There's a special form of sort constraint that operates on three > enumerables: xs, ys and zs. What it does is that it constrains e.g. xs > to be ys sorted using the positions specified in zs. Once again > it's the > problem of conveying a function with multiple arguments. Using the > suggestion for element constraints this could become something like > > constrain sort(xs).with_indices(zs).equal(ys) > > I'm not sure how readable that is. What about taking a page from the Rails book and doing something like: constrain sorted(xs, :indices => zs).equal(ys) ? > == Cardinality constraints == > > This is a fairly straightforward constraint, it counts the number of > occurrences in an array. For instance I might specify that an array of > variables must contain 3 instances of 5 (3 and 5 can also be > replaced by > variables). > > Again it's multiple arguments for a function. Maybe it's more readable > as the following. > > constrain number_of(y).in(xs).equal(z) Here again parameters seem like they might be OK. What's nice is that we can get more variations this way. For example count(enum) could count all elements while count(enum, :element => y) would be just the y elements in enum. James Edward Gray II