Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
sv_checker.Orch.vdmsl Maven / Gradle / Ivy
/*
Model that formalises rule checking of FMU (Functional Mock-up Unit) scalars. The model takes as input an initial scalar
with possibly undefined values for causality, variability and intial. First, the model
attempts to adjust any of the undefined values. Afterwards it checks
that the adjusted scalar follows the standard. If the adjusted scalar does follow the standard then the model
produces a meaningful error message indicating what the specific problem with the scalar configuration is.
Steps of individual FMU init:
(1) Read all scalar variables from FMU (a set of SV)
(2) Initialise the FMU according to the FMI standard,
i.e. set the default values of the scalar properties,
if not defined.
(3) Validate the scalar variables of the FMU
according to the FMI standard
*/
module Orch
imports from IO all, from VDMUtil all
definitions
types
-- The different causalities a scalar may specify
Causality = | | | | | ;
-- The different variabilities a scalar may specify
Variability = | | | | ;
-- The different initial values a scalar may specify
Initial = | | ;
Types = | | | | ;
StartValueTypes = [real | int | bool | seq of char | token];
-- The type of a scalar
Type ::
type : Types
startValue : StartValueTypes;
/*
Represents a scalar before it has been adjusted. At this point causality, variability as well as the
initial value might be undefined, which is indicated using the 'nil' value.
*/
SV ::
causality : [Causality]
variability : [Variability]
initial : [Initial]
type : Type;
/*
Represents a scalar after it has been adjusted. At this point only the initial value may be undefined,
which is indicated using the 'nil' value.
*/
SV' ::
causality : Causality
variability : Variability
initial : [Initial]
type : Type
functions
TypeOk : Type -> bool * seq of char
TypeOk (ty) ==
let mk_Type(t,s) = ty
in
if s=nil or
(t= and is_real(s)) or
(t= and is_int(s)) or
(t= and (is_bool(s) or s = 0 or s = 1)) or
(t= and (is_(s,seq of char)or len s=0 )) or --or len s=0
(t= and is_int(s))
then mk_(true, "Combination OK")
else
mk_(false, "Type and startvalue incompatible. Got: type " ^
VDMUtil`val2seq_of_char[Types](t) ^ " and start value " ^
VDMUtil`val2seq_of_char[StartValueTypes](s));
/*
Construction of initial values based on the "causality/variability" table on page 48
as well as the "initial" table on page 49
*/
CalcInitial : Causality * Variability -> [Initial]
CalcInitial(c,v) ==
cases c:
->
if v in set {, } then
else
nil, -- (A)
->
if(v in set {, }) then
else
nil, -- (B)
->
nil,--if(v in set {, }) then nil else nil, --(D)
->
if(v=) then
else
if (v in set {, }) then
else
nil, -- (A) and (C)
->
if(v=) then
else
if (v in set { , , , }) then
else
nil, -- (A), (B) and (C)
-> nil--if (v=) then nil, -- (E)
end
pre CausalityVariabilityOk(c,v).#1
post InitialOk(c,v,RESULT).#1;
/*
Takes a scalar value with possibly undefined properties and tries to
construct a valid scalar with the default values for the undefined
properties. See page 46 (causality default), page 47 (continuous default)
and page 49 (initial values)
*/
InitSV : SV -> SV'
InitSV(sv) ==
let mk_SV(c,v,i,t) = sv,
c' = if (c = nil) then else c,
v' = if (v = nil) then else v,
i' = if (i = nil) then CalcInitial(c', v') else i
in
mk_SV'(c', v', i', t)
pre
let cc = if sv.causality = nil then else sv.causality,
vv = if sv.variability = nil then else sv.variability
in
CausalityVariabilityOk(cc,vv).#1
post
let mk_SV'(c',v',i',-) = RESULT
in
(sv.causality = nil => c' = ) and
(sv.variability = nil => v' = ) and
((sv.initial = nil and CausalityVariabilityOk(c',v').#1) => InitialOk(c',v',i').#1);
TypeVariability : Variability * Type -> bool * seq of char
TypeVariability (v,t) ==
if v = => t.type = then
mk_(true,"Combination OK")
else
mk_(false, "For a continuous variable the type has to be Real");
/*
Constructs a string representation based on a valid combination of causality and variablity
as indicated by the table on page 50
*/
ValidSettingsToStr : Causality * Variability -> seq of char
ValidSettingsToStr(c ,v) ==
if c= and v= then
"fixed parameter"
elseif c= and v= then
"tunable parameter"
elseif c= and v= then
"fixed dependent parameter"
elseif c= and v= then
"tunable dependent parameter"
elseif c= and v= then
"discrete input"
elseif c= and v= then
"continuous input"
elseif c= and v= then
"constant output"
elseif c= and v= then
"discrete output"
elseif c= and v= then
"continuous output"
elseif c= and v= then
"constant local"
elseif c= and v= then
"fixed local"
elseif c= and v= then
"tunable local"
elseif c= and v= then
"discrete local"
elseif c= and v= then
"continuous local"
elseif c= and v= then
"continuous independent"
else
undefined
pre CausalityVariabilityOk(c,v).#1;
/*
Assuming that the scalar is invalid check if the causality and variable is the problem (see table on page 49)
*/
CausalityVariabilityOk : Causality * Variability -> bool * seq of char
CausalityVariabilityOk(c,v) ==
if c in set {, , } and v = then
mk_(false, ErrorMsg(c,v))
elseif c in set {, } and v in set {, } then
mk_(false, ErrorMsg(c,v))
elseif c= and v in set {, , , } then
mk_(false, ErrorMsg(c,v))
elseif c in set { ,} and v in set {, } then
mk_(false, ErrorMsg(c,v))
else
mk_(true, "Valid combination of Causality and Variability.")
post RESULT.#1 => ValidCV(c,v);
ValidCV : Causality * Variability -> bool
ValidCV (c,v) ==
((c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=) or
(c= and v=));
/*
Formatting of an error message
*/
ErrorMsg : Causality * Variability -> seq of char
ErrorMsg (c,v) ==
IO`sprintf("Invalid combination of causality and variability. For causality '%s' the expected variabilities are '%s' but got: '%s'",[c,ValidVariabilities(c),v])
pre not ValidCV(c,v);
/*
Takes a causality and returns the valid variabilities in accordance with
the causality/variability table on page 49
*/
ValidVariabilities : Causality -> set of Variability
ValidVariabilities(c) ==
cases c:
-> {, }, -- page 46
-> {, },
-> {, },
-> {, , },
-> { , , , , },
-> {}
end
post
forall v in set RESULT & CausalityVariabilityOk(c,v).#1;
/*
Only invoked when CheckSV has returned false
Checks if the initial value is valid based on the combination of causality and variability.
Returns true if initial is valid - false otherwise. If initial is invalid a proper error message
is also being returned, otherwise the message just indicates that the combination was okay.
*/
InitialOk : Causality * Variability * [Initial] -> bool * seq of char
InitialOk(c,v,i) ==
let EXPECT_SPECIFIC_VAL = "An invalid value of Initial. Actual: %s, but expected: %s " ^
"for the combination of causality: %s and variability: %s",
EXPECT_INITIAL_NOT_SET = "An invalid value of Initial. Actual: %s, but expected " ^
"inital not to be set for the combination of causality: %s and variability: %s",
INITIAL_NOT_DEFINED = "An invalid value of Initial. Actual: Initial not defined, " ^
"but expected: %s for the combination of causality: %s and variability: %s",
COMB_OK = "Initial OK"
in
cases c:
->
mk_(i in set {}, IO`sprintf(EXPECT_SPECIFIC_VAL, [i,,c,v])), -- page 46
->
mk_(i in set {,}, IO`sprintf(EXPECT_SPECIFIC_VAL, [i,{,},c,v])),
->
mk_(i=nil, IO`sprintf(EXPECT_INITIAL_NOT_SET, [i,{,},c,v])),
->
if (not(v = => i = )) then
mk_(false, IO`sprintf(EXPECT_SPECIFIC_VAL, [i,,c,v]))
elseif (not(v in set { , } => i in set {, , })) then
mk_(false, IO`sprintf(INITIAL_NOT_DEFINED, [i,{,,},c,v]))
else
mk_(true,COMB_OK),
->
if(not(v = => i=)) then
mk_(false, IO`sprintf(INITIAL_NOT_DEFINED, [i,,c,v]))
elseif(not(v in set { , } => i in set {, })) then
mk_(false, IO`sprintf(INITIAL_NOT_DEFINED, [i,{,},c,v]))
elseif(not (v in set { , } => i in set {, , })) then
mk_(false, IO`sprintf(INITIAL_NOT_DEFINED, [i,{,,},c,v]))
else
mk_(true,COMB_OK),
->
mk_(i=nil, IO`sprintf(EXPECT_INITIAL_NOT_SET, [i,{,},c,v]))
end
pre CausalityVariabilityOk(c,v).#1
post RESULT.#1 =ValidCVI(c,v,i);
ValidCVI : Causality * Variability * [Initial] -> bool
ValidCVI (c,v,i) ==
(
-- Case A:
(i = and ((v in set {,} and c = ) or (v = and c in set {,})))
or
-- Case B:
(i in set {,} and (v in set {,} and c in set {,}))
or
-- Case C:
(i in set {,,} and (v in set {,} and c in set {,}))
or
-- Case D:
(i = nil and (v in set {, } and c = ))
or
-- Case E:
(i = nil and (v = and c = ))
);
/*
Only invoked when CheckSV has returned false. This function constructs
an appropriate error message for the start value.
If the problem is not the causality, variability or the initial value
then the start value must be the problem.
*/
StartValueOk : Causality * Variability * [Initial] * Type -> bool * seq of char
StartValueOk(c,v,i,t) ==
let startValReq = true,
combOk = "Combination OK"
in
cases c:
->
if(not(i in set {, } => t.startValue <> nil)) then
mk_(false,InvalidStartValueToStr(startValReq,c,v,i))
else
mk_(true,combOk),-- page 46
->
if(not(i in set {, } => t.startValue <> nil)) then
mk_(false,InvalidStartValueToStr(startValReq,c,v,i))
else if (not(i = => t.startValue = nil)) then
mk_(false,InvalidStartValueToStr(not startValReq,c,v,i))
else
mk_(true,combOk),
->
if not t.startValue <> nil then
mk_(false,InvalidStartValueToStr(startValReq,c,v,i))
else
mk_(true,combOk),
->
if(not(i = => t.startValue = nil)) then
mk_(false,InvalidStartValueToStr(not startValReq,c,v,i))
elseif (not(i in set {, } => t.startValue <> nil)) then
mk_(false,InvalidStartValueToStr(startValReq,c,v,i))
else
mk_(true,combOk),
->
if(not(i = => t.startValue = nil)) then
mk_(false,InvalidStartValueToStr(not startValReq,c,v,i))
elseif (not(i in set {, } => t.startValue <> nil)) then
mk_(false,InvalidStartValueToStr(startValReq,c,v,i))
else
mk_(true,combOk),
->
if not t.startValue = nil then
mk_(false,InvalidStartValueToStr(not startValReq,c,v,i))
else
mk_(true,combOk)
end
pre ValidCV(c,v) and ValidCVI(c,v,i);
ValidStart : Causality * Variability * [Initial] * Type -> bool
ValidStart (c,v,i,t) ==
if (i in set{,}) or (c = ) then
t.startValue <> nil
elseif (i = or c = ) then
t.startValue = nil
elseif (c in set {, } or v = ) then
t.startValue <> nil
else
false;
InvalidStartValueToStr : bool * Causality * Variability * [Initial] -> seq of char
InvalidStartValueToStr(b,c,v,i) ==
if b then
IO`sprintf("A start value has to be set for a combination of " ^
"Causality: %s, Variability: %s and Initial: %s",[c, v, i])
else
IO`sprintf("A start value is not allowed to be set for a combination " ^
"of Causality: %s, Variability: %s and Initial: %s",[c, v, i]);
/*
The main function of the specification.
Takes as input an adjusted scalar and checks if the combination
of properties is valid.
The function returns a string representation of the scalar if it is valid.
If the scalar is not valid the function produces an error message, which
describes the problem with the specific choice of properties.
*/
Validate : SV' -> bool * seq of char
Validate(sv') ==
let mk_(tc_ok, tc_msg) = TypeOk(sv'.type)
in
if not tc_ok then
mk_(false, tc_msg)
else
let mk_(vt_ok, vt_msg) = TypeVariability(sv'.variability,sv'.type)
in
if not vt_ok then
mk_(false, vt_msg)
else
-- The combination of properties is not valid and we need to construct a suitable error message
--First check if causility and variability makes up an invalid combination
let mk_(cv_ok, cv_msg) = CausalityVariabilityOk(sv'.causality,sv'.variability)
in
if not cv_ok then
-- Causality and variability is not a valid combination so stop and return the error message
mk_(false, cv_msg)
else
-- Causality and variability makes up a valid combination. Check if the initial value is the problem
let mk_(ini_ok, ini_msg) = InitialOk(sv'.causality,sv'.variability,sv'.initial)
in
if not ini_ok then
mk_(false, ini_msg)
else
-- The initial value was also valid so the problem must be start value
let mk_(start_ok, start_msg) = StartValueOk(sv'.causality,sv'.variability,sv'.initial,sv'.type)
in
if not start_ok then mk_(false, start_msg)
else
mk_(true, "ScalarVariable is valid")
post
RESULT.#1 =
let mk_SV'(c,v,i,t) = sv'
in
TypeOk(t).#1 and
cases c:
->
v in set {, } and
(i in set {/*, */} => t.startValue <> nil) and-- page 46
i = , -- page 46
->
v in set {, } and --page 46
i in set {,} and-- page 46
(i in set {, } => t.startValue <> nil) and
(i =