From: Andreas Launila Date: 2007-06-07T16:30:21+09:00 Subject: Re: Gecode/R - Request for syntax feedback James Edward Gray II wrote: > 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. True, I have switched to sorted. > * 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. > Certainly, I have updated the page with this suggestion and all the others in your mail. >> == 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. > Yes. >> 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. > I will write up some similar syntax examples with proxy objects to see how big the difference is. >> == 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. ;) Actually I made a mistake in the examples of the two different viewpoints which might have confused a bit. It should be the following. First viewpoint: xs = [2,0,1,3] (the actual sequence) Second viewpoint: ys = [1,2,0,3] (the positions of the different numbers, e.g. the position of 0 in xs is 1, hence ys[0] == 1) > >> == 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) > > ? Yes, especially since indices is optional. > >> == 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. > I'm not sure if count(enum) would be used since it's basically the same as counting the number of elements in enum and constraining z to be equal to it (and since you constructed the enum you already know the size and could thereby replace z with that constant). But the form with an hash option is more readable than the form with just two arguments. -- Andreas Launila