在下面的ADA Spark示例中,如何阻止前置条件失败

在下面的ADA Spark示例中,如何阻止前置条件失败,ada,formal-methods,spark-ada,Ada,Formal Methods,Spark Ada,对于一个项目,我目前正试图为一架想象中的飞机编写一个小型飞行员辅助系统。任务是学习Ada Spark,而不是航空电子设备。我已经对我想要使用的飞机组件进行了建模,在主文件中进行了一些测试,以检查组件是否按预期工作,一切正常,现在我要在函数中添加前置和后置条件,以确保我的飞机超级安全。其中一项安全措施是确保飞机在拖航时发动机不能打开,反之亦然,在发动机打开时切换到拖航 我将一个引擎建模为一个高度复杂的记录,其中有一个属性,类型为OnOff,它可以打开或关闭其中一个值。注意,我计划扩展属性,因此它不

对于一个项目,我目前正试图为一架想象中的飞机编写一个小型飞行员辅助系统。任务是学习Ada Spark,而不是航空电子设备。我已经对我想要使用的飞机组件进行了建模,在主文件中进行了一些测试,以检查组件是否按预期工作,一切正常,现在我要在函数中添加前置和后置条件,以确保我的飞机超级安全。其中一项安全措施是确保飞机在拖航时发动机不能打开,反之亦然,在发动机打开时切换到拖航

我将一个引擎建模为一个高度复杂的记录,其中有一个属性,类型为OnOff,它可以打开或关闭其中一个值。注意,我计划扩展属性,因此它不会保持一个属性记录

这是发动机规格文件

package engines with SPARK_Mode
is

type OnOff is (On, Off);
type Engine is record
  isOn: OnOff;
end record;


procedure switchOn (x : in out Engine);
procedure switchOff (x : in out Engine);

end engines;
我的飞机是这样组装的:

   type Plane is record
     engine1: Engine;
     engine2: Engine;
     gearOfLanding: LandingGear;
     doorPax1, doorPax2, doorServ1, doorServ2, 
     doorCockpit: Door;
     panelOfReadings: ReadingsPanel;
     panelOfAlerts: AlertsPanel;
     planOfFlight: FlightPlan;
     speedLimits: SpeedLimit;
     altitudeLimits: AltitudeLimit;
     attitudeLimits: AttitudeLimit; 
     litresPerMile: Integer;
     fuelTank1: FuelTank;
  end record;
planes文件中的SwitchOneEngine过程将引擎作为输入,并从engines文件调用switchOn。以下是规范和正文:

  procedure switchOnEngine (x : in out Engine; y : in Plane) with
    Pre => y.panelOfReadings.mode /= Tow,
    Post => x = (isOn => On) and y.panelOfReadings.mode /= Tow;



  procedure switchOnEngine (x : in out Engine; y : in Plane)
  is
  begin
      switchOn(x);
  
  end switchOnEngine;
该平面作为变量传入,因此我可以检查各种属性的前置和后置条件,但我收到的警告消息不确定如何解决

precondition might fail
cannot prove y.panelOfReadings.mode /= Tow e.g when .......mode =>Tow
下面的一行也给出了我控制飞机的主文件中的一个错误

switchOnEngine(AirForceOne.engine1, AirForceOne);

formal parameters x and y are aliased, and this is being marked as a 'high' priority warning.
这是主文件中飞机的初始化

AirForceOne : Plane := (
   engine1 => (isOn => Off),
   engine2 => (isOn => Off),
   litresPerMile => 5,
   gearOfLanding => (isExtended => Extended),
   doorPax1 => (isClosed => Closed, isLocked => Unlocked),
   doorPax2 => (isClosed => Closed, isLocked => Unlocked),
   doorServ1 => (isClosed => Closed, isLocked => Unlocked),
   doorServ2  => (isClosed => Closed, isLocked => Unlocked),
   doorCockpit => (isClosed => Closed, isLocked => Unlocked),
   fuelTank1 => (capacity=>26000, currentFuel=>26000),
   planOfFlight => (distFromDest => 1500),
   panelOfReadings =>
       (mode => Tow,
        currentSpeed => 0,
        altitud => 0,
        attitud =>
            (currentPitch=>0,
             currentRoll =>0)
       ),
   panelOfAlerts =>
       (approachingStallSpeed => Off,
        unRestrictedSpeed => Off,
        withinLandingSpdRange => Off,
        withinOptCruiseAlt => Off,
        withinOptCruiseSpeed => Off,
        takeoffSpeedReached => Off,
        fuelStatus => Off,
        maxPitchAngleExceeded => Off,
        maxRollAngleExceeded => Off),
   speedLimits =>
       (minLanding => 180,
        maxLanding => 200,
        minStall => 110,
        minTakeoff => 130,
        maxRestricted => 300,
        maxGroundMode => 10),
   altitudeLimits =>
       (minFlight => 500,
        maxFlight => 41000,
        optCruiseAlt => 36000,
        maxRestrictedSpeed => 10000,
        maxInitiateFlareMode => 100),
   attitudeLimits =>
       (maxRoll => 30,
        maxPitch => 30,
        minRoll => -30,
        minPitch => -30)
 );

任何帮助都会很好。我原以为在前提条件下建议飞机不能拖航就足够了,但这似乎还不够。

SwitchOneEngine的目的是改变飞机的状态。编写它来改变引擎的状态将使事情变得复杂

Max_Engines : constant := 100; -- The Lillium jet has 36, so I hope this is enough

type Engine_Num is range 1 .. Max_Engines;

type Engine_Info is ...

type Engine_Map is array (Engine_Num range <>) of Engine_Info with
   Dynamic_Predicate => Engine_Map'First = 1;

type Plane_Info (Num_Engines : Engine_Num) is record
   Engine : Engine_Map (1 .. Num_Engines);
   ...

procedure Turn_On (Engine : in Engine_Num; Plane : in out Plane_Info) with
   Pre => Engine in 1 .. Plane.Num_Engines and then
          (not Running (Plane.Engine (Engine) ) and not Under_Tow (Plane),
   Post => Running (Plane.Engine (Engine) );

Air_Force_One : Plane_Info (Num_Engines => 4);
Max_引擎:常数:=100;——Lillium喷气式飞机有36个,所以我希望这足够了
类型引擎数量为范围1。。最大功率发动机;
类型引擎信息是。。。
type Engine_Map是带有
动态_谓词=>Engine_Map'First=1;
记录类型平面信息(Num\u引擎:Engine\u Num)
引擎:引擎映射(1..Num\u引擎);
...
使用以下步骤打开(引擎:引擎内数量;平面:平面内信息)
Pre=>发动机在1。。Plane.Num_引擎,然后
(未运行(飞机、发动机)且未被牵引(飞机),
Post=>运行(飞机发动机(发动机));
空军一号:飞机信息(引擎数量=>4);

程序SwitchEngineen采用两个独立的参数,一个飞机和一个发动机。飞机和两个发动机中的一个发动机之间没有逻辑连接。因此,被牵引的飞机和发动机状态之间没有逻辑连接。“ADA Spark”:Ada不是首字母缩略词;SPARK是选择好的名字对于书写正确的S/W很重要。X不是发动机的好名字,Y也不是飞机的好名字。如果X不是Y的发动机,会发生什么?你怎么知道?这里有很多有用的答案谢谢很多人我知道我错在哪里了。我刚刚回到我的飞机工作中,非常感谢你再一次。我基本上删除了我的飞机记录,并将所有属性设置为全局值,完全简化了它。考虑到我使用Ada的经验,尝试应用良好的OOP实践使它变得太复杂了,你的回答确实澄清了我的错误。