Search code examples
enumsalloyfirst-order-logicdeclarative-programming

Value assignment in Alloy and use of Enum


How to assign variable in Alloy?

Sig ClassA{
    variable_1: String,
    variable_2: Int
}

Sig ClassB{
    variable_1: String,
    variable_2: Int
}

pred isLess[a:ClassA,b:ClassB]{
    a.variable_2 < b.variable_2
}

assert integrityTest{
    all a:ClassA,b:ClassB| isLess[a,b]

}

Now I want to check counterexample of variables when I assign some bigger value in a.variable_2 than b.variable_2. But I am not sure how to assign variable in Alloy. Only thing I came up with is following but it is not working-

pred assignValue[a:ClassA]{
    a.variable_2 = Int[4]  
}

However, I believe it will only check the equality with 4 and return as false. It has nothing to do with the assignment. So my question is how should I produce counterexample when a.variable_2>b.variable_2

And How can I use Enum of Int in alloy? Like- Enum MetricValue {1,2,3,4,5} to assign a.variable 1.

EDIT I am still having trouble finding the counterexample, even though I can find one by manually checking when I toggle the value of variable_2 of ca and cb.

 sig ClassA{ 
    variable_1: String, 
    variable_2 = Int 
 } 

 sig CA extends ClassA{}{ 
    variable_2 = 1 
 } 
 sig ClassB{ 
    variable_1: String,
    variable_2 = Int 
 } 
 sig CB extends ClassB{}{ 
    variable_2 = 4 
 }

 pred checkAllConstraint [ca: ClassA, cb: ClassB] { 
    ca.variable_2 > cb.variable_2 } 

  assert checkAll{ 
    all ca: ClassA, cb: ClassB | checkAllConstraint[ca,cb] 
  } 
  check checkAll for 15

Solution

  • You can restrain a field to a single value through facts. In your case, signature facts come handy.

    It will look like this:

    sig ClassA{
      variable_1: String,
      variable_2: Int
    }{
        variable_1="hello world"
        variable_2=4
    }
    

    To bound a field to one value amongst a set, you can use the "in" keyword instead of "=" as follows:

    sig ClassA{
    variable_1: String,
    variable_2: Int
    }{
        variable_1 in ("hello" + "world")
        variable_2 in (1+2+3+4)  
    }
    

    Note that in Alloy + is a UNION operator. It doesn't sum nor concatenate as you might expect.

    EDIT It doesn't work for 2 reasons:

    • you wrote : variable_2 = Int instead of variable_2: Int. By doing so, no valid instance contains atoms typed by CA or CB, because e.g. ClassA.variable2 is constrained to be the set of all integers and CA.variable2 is constrained to be 1
    • no String atom is defined. That's one of Alloy's weird part. If you want to use Strings in your model, you need to have string litterals somewhere specified, e.g. in a fact.

    Here's your model, corrected:

    sig ClassA{ 
        variable_1: String, 
        variable_2 : Int 
     } 
    
     sig CA extends ClassA{}{ 
        variable_2 = 1 
     } 
     sig ClassB{ 
        variable_1: String,
        variable_2 : Int 
     } 
     sig CB extends ClassB{}{ 
        variable_2 = 4 
     }
    
     pred checkAllConstraint [ca: ClassA, cb: ClassB] { 
        ca.variable_2 > cb.variable_2 } 
    
      assert checkAll{ 
        all ca: ClassA, cb: ClassB | checkAllConstraint[ca,cb] 
      } 
      check checkAll for 15
    
    fact { String in ("test"+"test2"+"test3"+"test4")}
    

    If you still have questions, please create a new one.

    -