On Jun 6, 2007, at 5:21 AM, Andreas Launila wrote:

> James Edward Gray II wrote:
>> On Jun 5, 2007, at 2:43 PM, Andreas Launila wrote:
>>
>>> == Issues ==
>>>
>>> === Describing (linear) constraints ===
>>
>>> A problem with the above is that people might look at it and
>>> instinctively think that it's something that does not have a side
>>> effect. Therefore prepending some sort of method might convey that
>>> intention better. For instance we could allow people to write the
>>> following.
>>>
>>> constrain x + y == z
>>
>> RSpec works a lot like this.  It has you define expectations with  
>> syntax
>> like:
>>
>>   some_obj.should     equal(whatever)
>>   some_obj.should_not equal(whatever)
>>
>>> Fitting words other than "constrain" might be "assert", "post" and
>>> "add".
>>
>> I like the word "constrain."  If you go the RSpec route though,  
>> you will
>> probably also want a negative form and I don't know what that  
>> would be.
>>
>
> That would be a nice solution. The best word I can think of for
> "constrain" is "constrain_negation", which is probably far from  
> perfect.
>
> constrain_negation x + y == z

Yuck.  And I mean that in the nicest possible way.  ;)

> Another variation would be to use a combination of constrain and  
> RSpec's
> should/should_not.
>
> constrain (x + y).must == z
> constrain (x + y).must_not == z

That's not too bad.  I think my biggest complaint there is that it  
makes the flow of the line a little hard to follow.  Perhaps must/ 
must_not could replace constrain altogether though:

must     x + y == z
must_not x + y == z

That doesn't read too well though, does it?

> As an example there's a domain
> constraint which basically says that x must be in a given range.
> Negating the constraint is possible and might be written as follows.
>
> constrain x.in(1..17)
> constrain x.not_in(1..17)

This seems like a very viable solution to me.  If it's possible to  
just negate all of the tests, that should work:

equal/not_equal
in/not_in
includes/does_not_include

>>> === Overall syntax ===
>>>
>>> Every model has at least three parts:
>>> * Declaration of variables (in the example that would be "squares  
>>> = ...")
>>> * Definition of constraints (all the lines from  
>>> "all_distinct ..." down
>>> to "squares.diagonal..." in the example).
>>> * Selection of branching strategy (the line starting with  
>>> "branch_on" in
>>> the example)
>>>
>>> Maybe that could be used to produce some other overall syntax? E.g.
>>> something other than throwing it all into a constructor.
>>
>> Reading this definitely made me wonder over a DSL.  That's pretty  
>> much
>> what you have with the class system though.  If constrain()  
>> becomes the
>> constraint definer and branch_on() represents the branching strategy,
>> the only thing you haven't really wrapped is the variable  
>> declaration.
>>
>> I don't know what that would look like, but maybe something like:
>>
>>   variable :some_name, :int, accepted_range_of_values
>>
>> Then I guess you could later refer to them by name.  Of course,  
>> that's
>> just not as convenient when it comes to accessing them.  Iterating  
>> over
>> rows and columns shows this well.
>
> I don't understand the part about not being as convenient to  
> access. I'm
> assuming that one could define matrices just as well as single  
> variables
> with such a syntax, which would basically give the same level of
> convenience. An example to see if I understood you correctly (possibly
> with some keys for the parameters beyond the name and type):
>
> class MagicSquare < Gecode::Model
>   def initialize(n)
>     variable :squares, :int_matrix, n, n, 1..(n**2)
>     squares.row(0)
>     ...
>   end
> end

I think this makes it more complicated to support custom data  
structures.  What if I want a MyUniqueDataStructure full of IntVars,  
for example?

Beyond that, it doesn't seem in anyway superior to:

   class MagicSquare < Gecode::Model
     def initialize(n)
       @squares = ...
     end
     attr_reader :squares
   end

I think it's probably best not to override core Rubyisms if we can't  
significantly add to them.

James Edward Gray II