谓词世界生成中的问题

时间:2018-11-07 12:08:59

标签: alloy

在世代的最后一个谓词上我遇到了一个问题,尽管签名超过3个,但仅显示了3个。

我想念什么?

我需要在pred show(){}中指定内容吗? 我需要运行谓词来强制特定数量的对象吗?

open util/boolean

// Signatures


abstract sig Sensor {
    available: one Bool
}

sig HeartRateSensor extends Sensor{}
sig BloodPressureSensor extends Sensor{}
sig SleepMonitoringSensor extends Sensor{}


sig Smartwatch {
    user: one User,
    sensors: set Sensor,
    compatible: one Bool
} {
    // Must have at least 3 different sensors:
    // HeartRateSensor, BloodPressureSensor, SleepMonitoringSensor
    all disj s, s', s'': Sensor {
        ((s in sensors && s' in sensors && s'' in sensors) &&
        (s != s' && s' != s'' && s != s'') && 
    ( s.available = True && s'.available = True && s''.available = True)) <=> compatible = True
    }
}


abstract sig Customer {
    username: lone String, 
    password: lone String,
    canRegister: one Bool,
    isRegistered: one Bool
} {
    isRegistered = True => canRegister = True
    canRegister = False => isRegistered = False
    #username = 0 || #password = 0 => canRegister = False 
}

sig User extends Customer {
    fiscalCodeOrSSN: lone String,
    smartwatch: one Smartwatch,
    notifications: set Notification, 
    acceptsDataRequestFrom: set Company
} {
    (#fiscalCodeOrSSN = 0 || smartwatch.compatible = False) => canRegister = False
}

sig Company extends Customer {
    paymentMethod: lone String,
    queries: set Query
} {
    #paymentMethod = 0 => canRegister = False
    isRegistered = False => #queries = 0
}

abstract sig Query {
    company: one Company
}

sig AnonQuery extends Query {
    people: set User,
    isValid: one Bool
} {
    isValid = True <=> #people >= 5
}

sig IndividualQuery extends Query {
    person: one User,
    userAccepts: lone Bool, // lone cause if #userAccepts = 0 it must mean that a notification had been received by the user
} {
    all u: User {
        u = person => userAccepts = True else #userAccepts = 0 && #person.notifications > 0
    }
}

sig Notification {
    user: one User,
    company: one Company
}

// Facts: Consistency

fact UsernameConsistency {
    // There are no 2 Customer(s) with the same username
    all disj c, c': Customer | c.username != c'.username
}

fact FiscalCodeOrSSNConsistency {
    // There are no 2 User(s) with the same fiscalCodeOrSSN
    all disj u, u': User | u.fiscalCodeOrSSN != u'.fiscalCodeOrSSN
}

fact SmartWatchConsistency {
    // Let's suppose, wlog, that the cardinality of the relation
    // between smartwatch and user is 1 to 1
    all s: Smartwatch, u: User | s.user = u <=> u.smartwatch = s
}

fact QueryConsistency {
    // If a query has been made by a company
    // it must be in the set of all the queries 
    // made by the company
    all q: Query, c: Company | q.company = c <=> q in c.queries
}

fact NotificationConsistency {
    // If a notification has been sent to a user
    // the user must have it in the set of 
    // all notifications
    all n: Notification, u: User | n.user = u <=> n in u.notifications
}

// Assertions 

// Goal G2: The system should allow users to register by providing his 
// Fiscal Code or his Social Security Number, an username and a password. 

assert UserCanRegister {
    all u: User {
        (
            #u.username = 1 && 
            #u.password = 1 && 
            #u.fiscalCodeOrSSN = 1 &&
            u.isRegistered = False && 
            u.(smartwatch.compatible) = True
        ) => u.canRegister = True
    }
}

check UserCanRegister for 5

// Goal G3: The system should allow companies to register

assert CompaniesCanRegister {
    all c: Company {
        (
            #c.username = 1 && 
            #c.password = 1 &&  
            #c.paymentMethod = 1 
        ) => c.canRegister = True
    }
}

check CompaniesCanRegister for 5

// Goal G4: The system should allow registered companies to request data
// from an anonymized group of individuals, only if individuals in the
// group are more than 1000.

assert CompaniesCanMakeAnonimizedQueries {
    all c: Company, q: AnonQuery{
        (
            c.isRegistered = True && 
            #queries > 0 && 
            #q.people >= 5
        ) => q.isValid = True && q in c.queries

    }
}

check CompaniesCanMakeAnonimizedQueries for 5

// Goal G5: The system should allow registered companies to request data
// from an individual person, only if individuals accept the request.

assert CompaniesCanMakeIndividualQueries {

    // If a company requests data from a single person 
    // either
    // the person accepts <=> company is in the person acceptance list
    // or 
    // the person still hasn't accepted => there's a notification concerning the company and the user in the person notification list

    all q: IndividualQuery, c: Company, n: Notification {
        (q.company = c) &&
        (
            (q.userAccepts = True <=> c in q.(person.acceptsDataRequestFrom)) ||
            (#q.userAccepts = 0 => (
                n.user = q.person && 
                n.company = c && 
                n in q.(person.notifications)
            )) 
        )
    }

}

check CompaniesCanMakeAnonimizedQueries for 5

pred show(){}

run show for 10

2 个答案:

答案 0 :(得分:0)

没关系,我只是想通了。

开个玩笑,问题是在声明String类型的属性时出现了奇怪的行为。用“自定义”签名(例如sig Charset {})替换String声明可以使世界正确显示。

答案 1 :(得分:0)

请参阅答案:How to model a consitent database in alloy?

要使内置签名String起作用,您必须初始化一个String类型原子的自定义“池”。

在您的情况下,我将对具有字符串类型字段的每个签名执行以下操作:

sig Company extends Customer {
    paymentMethod: lone String,
    queries: set Query
} {
    payementMethod in "PayPal"+ "Bank Transfer"+"Credit Card"
    ...
}