Eiffel: Expanded classes with no fields are `=` or not? - operators

In Eiffel, if comparing objects of an expanded type, the = operator compares them field by field, checking if the content of each field is identical in both objects.
Let's imagine two expanded classes with no features defined in them:
expanded class A
end
expanded class B
end
How can Eiffel tell them apart? Or can't it? Does it have to do with some field(s) inherited from ANY?
both_are_equal: BOOLEAN
local
a: expanded A
b: expanded B
do
Result := a = b
end

The field-by-field comparison is applied only when both objects are of the same type. If they are of different types the equality operator gives false. In other words, the equality operator = for expanded types is identical to the equality operator ~ with the semantics
type_of (a) = type_of (b) and then a.is_equal (b)
Therefore both_are_equal will give False.
The result will be the same if instead of a and b of expanded types there will be x and y of reference types attached to expanded objects - the comparison takes types of objects into account:
both_are_equal: BOOLEAN
local
a: expanded A
b: expanded B
x: ANY
y: ANY
do
x := a
y := b
Result := x = y -- Gives False
end
But if the reference expressions are attached to expanded objects of the same type, field-by-field comparison is used, not reference equality:
both_are_equal: BOOLEAN
local
a: expanded A
b: expanded A -- Note the type change
x: ANY
y: ANY
do
x := a
y := b
Result := x = y -- Gives True even though x and y are different objects
end
Some details on equality operators can be found in the Standard ECMA-367 (section 8.21) and in contracts of specific comparison features in the class ANY.

Related

Z notation specification to modify content of a set

Let's say I have a set:
S: Id X Counter
Id: \nat
Counter: \nat
Need help to define an operation filter which takes in two parameters, x:\nat and y:\nat which I can apply to S. This function will match on the first parameter with \exists a \in S # first(a) = x and then reduce second(a) with y. If the value is less than or equal to zero, a should be removed from the set S, otherwise (first(a), second(a) - y) should replace a.
If the above is indecipherable, just please give me any example definition that operates over a set and modifies it.
Thanks.

How to set up simple two domain constraint on a variable in Pyomo?

I am working on a supply chain optimisation problem using Pyomo and I need to set up a constraint on specific variables in the model. The constraint is that the variable should be within the set (0,1) or (200, to infinity). However, when I try to set up that constraint I am getting a TypeError, here is my code:
def rail_rule(model):
for route in routes:
if "rail" in route[0].lower():
dest = route[0]
dg = route[1]
sg = route[2]
site = route[3]
return model.x[dest, dg, sg, site]>=200 or model.x[dest, dg, sg, site]<=1
model.railconst = Constraint(rule = rail_rule)
I get this error when I run it :
TypeError: Relational expression used in an unexpected Boolean context.
The inequality expression:
200.0 <= x[RAIL - KENSINGTON,8,8,BROCKLESBY]
contains non-constant terms (variables) that were evaluated in an
unexpected Boolean context at
File '<ipython-input-168-901363ebc86f>', line 8:
return model.x[dest, dg, sg, site]>=200 or model.x[dest, dg, sg, site]<=1
Evaluating Pyomo variables in a Boolean context, e.g.
if expression <= 5:
is generally invalid. If you want to obtain the Boolean value of the
expression based on the current variable values, explicitly evaluate the
expression using the value() function:
if value(expression) <= 5:
or
if value(expression <= 5):
So my understanding is that I cant give Pyomo a boolean expression as a constraint, but I am quite new to Pyomo and not too sure if that's what my issue is or if I am doing it correctly.
This constraint could also be implemented in the variable intialisation as boundaries, but I cant find a way to set up two boundaries on a single variable in Pyomo.
Thanks !
There are different ways to handle this:
(1) Use binary variables. Assume you have a good upper bound on x, i.e., x ∈ [0, U]. Then formulate the constraints
x ≤ 1 + (U-1) δ
x ≥ 200 δ
δ ∈ {0,1} (binary variable)
This is the easiest way.
(2) If you don't have a good upper bound on x, you can use a SOS1 set. (SOS1 means Special Ordered Set of type 1). Assume x,s1,s2 ≥ 0.
x ≤ 1 + s1
x ≥ 200 - s2
s1,s2 ∈ SOS1 (s1,s2 form a SOS1 set)
(3) Use disjunctive programming.

When (exactly) can equality be proposed between different types using '='?

In the documentation, it says:
Equality in Idris is heterogeneous, meaning that we can even propose
equalities between values in different types:
idris_not_php : 2 = "2"
That particular example compiles, but the hole is presented as being of type fromInteger 2 = "2". Given that fromInteger 2 can belong to any type that is an instance of Num, maybe the compiler isn't quite clever enough to deduce that the value of 2 is not a String?
In comparison, the following slightly different code fails to compile:
idris_not_php : S (S Z) = "2"
The compiler reports a type mismatch between Nat and String.
Also, the following does compile successfully:
Num String where
(+) x y = y
(*) x y = y
fromInteger n = "2"
idris_not_php : 2 = "2"
idris_not_php = the (the String 2 = "2") Refl
And these two compile:
idris_not_php : S (S Z) ~=~ "2"
idris_not_php = ?hole
two_is_two : 2 ~=~ 2
two_is_two = Refl
Is there any particular rule about when = can be used between things that are of different types, or is it just a matter of using ~=~ when = doesn't work? Are ~=~ and = semantically identical, and if so, why is ~=~ even necessary?
This answer have some theoretical notes about heterogeneous equality in Idris. And this answer has example of why you may need (~=~).
I just want to add a little about idris_not_php : 2 = "2" example. This can be type checked if you have Num instance for String type just as you did. Integral constants in Idris are polymorphic. Though, any reasonable program wouldn't have such instance for String because it doesn't make sense.

Does "<-" mean assigning a variable in Haskell?

Just started Haskell, it's said that everything in Haskell is "immutable" except IO package. So when I bind a name to something, it's always something immutable? Question, like below:
Prelude> let removeLower x=[c|c<-x, c `elem` ['A'..'Z']]
Prelude> removeLower "aseruiiUIUIdkf"
"UIUI"
So here:
1. “removeLower" is an immutable? Even it's a function object?
But I can still use "let" to assign something else to this name.
2. inside the function "c<-x" seems that "c" is a variable.
It is assigned by list x's values.
I'm using the word "variable" from C language, not sure how Haskell name all its names?
Thanks.
If you're familiar with C, think of the distinction between declaring a variable and assigning a value to it. For example, you can declare a variable on its own and later assign to it:
int i;
i = 7;
Or you can declare a variable and assign initial value at the same time:
int i = 7;
And in either case, you can mutate the value of a variable by assigning to it once more after the first initialization or assignment:
int i = 7; // Declaration and initial assignment
i = 5; // Mutation
Assignment in Haskell works exclusively like the second example—declaration with initialization:
You declare a variable;
Haskell doesn't allow uninitialized variables, so you are required to supply a value in the declaration;
There's no mutation, so the value given in the declaration will be the only value for that variable throughout its scope.
I bolded and hyperlinked "scope" because it's the second critical component here. This goes one of your questions:
“removeLower" is an immutable? Even it's a function object? But I can still use "let" to assign something else to this name.
After you bind removeLower to the function you define in your example, the name removeLower will always refer to that function within the scope of that definition. This is easy to demonstrate in the interpreter. First, let's define a function foo:
Prelude> let foo x = x + 2
Prelude> foo 4
6
Now we define an bar that uses foo:
Prelude> let bar x = foo (foo x)
Prelude> bar 4
8
And now we "redefine" foo to something different:
Prelude> let foo x = x + 3
Prelude> foo 4
7
Now what do you think happens to bar?
Prelude> bar 4
8
It remains the same! Because the "redefinition" of foo doesn't mutate anything—it just says that, in the new scope created by the "redefinition", the name foo stands for the function that adds three. The definition of bar was made in the earlier scope where foo x = x + 2, so that's the meaning that the name foo has in that definition of bar. The original value of foo was not destroyed or mutated by the "redefinition."
In a Haskell program as much as in a C program, the same name can still refer to different values in different scopes of the program. This is what makes "variables" variable. The difference is that in Haskell you can never mutate the value of a variable within one scope. You can shadow a definition, however—uses of a variable will refer to the "nearest" definition of that name in some sense. (In the case of the interpreter, the most recent let declaration for that variable.)
Now, with that out of the way, here are the syntaxes that exist in Haskell for variable binding ("assignment"). First, there's top-level declarations in a module:
module MyLibrary (addTwo) where
addTwo :: Int -> Int
addTwo x = x + 2
Here the name addTwo is declared with the given function as its value. A top level declaration can have private, auxiliary declarations in a where block:
addSquares :: Integer -> Integer
addSquares x y = squareOfX + squareOfY
where square z = z * z
squareOfX = square x
squareOfY = square y
Then there's the let ... in ... expression, that allows you to declare a local variable for any expression:
addSquares :: Integer -> Integer
addSquares x y =
let square z = z * z
squareOfX = square x
squareOfY = square y
in squareOfX + squareOfY
Then there's the do-notation that has its own syntax for declaring variables:
example :: IO ()
example = do
putStrLn "Enter your first name:"
firstName <- getLine
putStrLn "Enter your lasst name:"
lastName <- getLine
let fullName = firstName ++ " " ++ lastName
putStrLn ("Hello, " ++ fullName ++ "!")
The var <- action assigns a value that is produced by an action (e.g., reading a line from standard input), while let var = expr assigns a value that is produced by a function (e.g., concatenating some strings). Note that the let in a do block is not the same thing as the let ... in ... from above!
And finally, in list comprehension you get the same assignment syntax as in do-notation.
It's referring to the monadic bind operator >>=. You just don't need to explicitly write a lambda as right hand side parameter. The list comprension will be compiled down to the monadic actions defined. And by that it means exactly the same as in a monadic environment.
In fact you can replace the list comprension with a simple call to filter:
filter (`elem` ['A' .. 'Z']) x
To answer your question regarding the <- syntactic structure a bit clearer:
[c| c <- x]
is the same as
do c <- x
return c
is the same as
x >>= \c -> return c
is the same as
x >>= return
Consider the official documentation of Haskell for further reading: https://hackage.haskell.org/package/base-4.8.2.0/docs/Control-Monad.html#v:-62--62--61-
[c|c<-x, c `elem` ['A'..'Z']]
is a list comprehension, and c <- x is a generator where c is a pattern to be matched from the elements of the list x. c is a pattern which is successively bound to the elements of the input list x which are a, s, e, u, ... when you evaluate removeLower "aseruiiUIUIdkf".
c `elem` ['A'..'Z']
is a predicate which is applied to each successive binding of c inside the comprehension and an element of the input only appears in the output list if it passes this predicate.

Promoting the left hand side of an assignment operator

I've written a Matlab class to handle dual numbers to do automatic differentiation. For almost all cases this works fine, and the new class is a drop-in replacement for the other numeric classes in most functions (the field 'x' gives the values of the function, and the field d gives the value of the derivative of the function at that point.)
>> x = mkdual([1 2 3]);
>> x.^2
ans =
Dual
Properties:
x: [1 4 9]
d: [2 4 6]
However, it fails when a function pre-allocates an output array, and assigns to the array by indexing into it. For example, the following is a common pattern in Matlab:
>> y=zeros(2) // Pre-allocate for speed
y =
0 0
0 0
>> x = 1;
>> y(1,:)=x
y =
1 1
0 0
Unfortunately this fails with my class, since it can't promote the array on the LHS of the assignment operator to a dual number:
>> x=mkdual(1);
>> y(2,:)=x
??? The following error occurred converting from Dual to double:
Error using ==> double
Conversion to double from Dual is not possible.
Can anyone suggest a fix or a workaround - preferably one which allows automatic promotion of the variable y to a Dual?
Your example isn't failing because it can't promote y to a Dual; it's failing because it tries to convert x to a double, and can't.
If you wanted to do that, you could add an overloaded double method to Dual that would do the conversion operation.
I'm guessing that's not what you want though, but rather you want a way of preallocating an array of dummy elements of class Dual. To do that you can design the constructor of Dual so that it will run with no input arguments, returning a dummy or default Dual. Then you can say y(2,2) = Dual and you'll have a 2x2 preallocated array of dummy Duals.
Search in the doc for 'Initializing arrays of value objects' for a fuller example.
Alternatively, you could make y a cell array instead of an array.
You will not be able to automatically promote y to a Dual, unless you are replacing the variable in its entirety (which defeats the benefits of preallocation).
However, you should be able to preallocate it as a Dual in the first place. I'm not sure of the syntax, and it may depend on your implementation, but something like:
mkdual(zeros(10,10))
Alternatively, you can do a lazy pre-allocation by loop backwards. That is, instead of
for ix = 1:100
y(ix) = mkdual(...)
end
Use
for ix = 100:-1:1
y(ix) = mkdual(...)
end