Z Notation is a formal specification language used to describe and model complex systems. It was developed in the 1970s by Jean-Raymond Abrial, a computer scientist at the Oxford University Computing Laboratory. The language was designed to be precise, unambiguous, and machine-readable, making it useful for specifying and verifying software and hardware systems.

Part 1: Writing Z Notation
Z Notation is based on mathematical set theory and logic, and uses a concise, symbolic notation to describe systems. It consists of a set of types, operators, and schemas, which can be combined to define complex structures. Here's a brief overview of some of the basic components of Z Notation:

Types: Z Notation defines several basic types, including natural numbers, integers, booleans, and sets. Types can be combined using set operations to define more complex types.

Operators: Z Notation includes a set of operators that can be used to manipulate values of different types. For example, the addition operator (+) can be used to add two numbers together, while the membership operator (in) can be used to check if an element is a member of a set.

Schemas: Schemas are the building blocks of Z Notation specifications. They define a set of variables and their relationships, and can be used to specify constraints and properties of a system.

Part 2: Example of Z Notation
Here's a simple example of how Z Notation can be used to describe a system:

Consider a system that models a simple bank account. We can use Z Notation to define the basic types and operators, as well as a schema that specifies the properties of the account. Here's an example:

```
BankAccount == $ \lblot balance: \num \rblot $

Deposit == \Delta BankAccount \\
\indent \texttt{deposit: \num \fun BankAccount}

Withdraw == \Delta BankAccount \\
\indent \texttt{withdraw: \num \fun BankAccount}

\texttt{BalanceInvariant} == \forall b: BankAccount @ \\
\indent \texttt{b.balance \geq 0}
```

In this example, we define a BankAccount type, which consists of a single attribute, balance. We also define two operations, Deposit and Withdraw, which take a BankAccount object as input and return a modified BankAccount object with the appropriate deposit or withdrawal applied. Finally, we define a BalanceInvariant schema, which specifies that the balance of a BankAccount must always be greater than or equal to zero.

Part 3: Applications of Z Notation
Z Notation is useful for a variety of applications, including software specification, hardware design, and system modeling. Its precision and formalism make it useful for verifying the correctness of systems, as well as for detecting errors and inconsistencies in complex designs.

One area where Z Notation has been particularly useful is in the design and verification of safety-critical systems, such as aircraft control systems and nuclear power plants. By using Z Notation to specify and verify the properties of these systems, engineers can ensure that they are safe and reliable.

Conclusion:
Z Notation is a powerful tool for specifying and modeling complex systems. Its precise, formal language makes it ideal for designing and verifying safety-critical systems, as well as for detecting errors and inconsistencies in software and hardware designs. By mastering the basics of Z Notation, beginners can gain a valuable skillset that will serve them well in a variety of technical fields.