Fault diagnosis of PLC-based discrete event systems using Petri nets

This paper addresses the fault diagnosis problem of PLC-based systems that can be modeled as Petri nets under a certain level of abstraction. The existing Petri-net-based fault diagnosis approaches often associate transitions and/or places with sensors and require that any change in sensor readings needs to be treated by a PLC, leading to a situation that the PLC would be too busy processing the changes in sensor readings to perform other tasks. This paper assumes that a PLC does not monitor the changes of readings of sensors all the time, but periodically reads the values of sensors when needed. The system output is defined as a marking sequence interleaved with possible observed transitions. A fault diagnosis algorithm is developed by defining and solving integer linear programing (ILP) problems whose size is regardless of the length of the system output. The proposed approach enjoys high computational efficiency compared with other ILP-based approaches and is more suitable for fault diagnosis of PLC-based systems with low computing power.


Position of this paper
The rapid development of electronic technology has made the computer-integrated systems, which can be abstracted as discrete event systems (DESs), 1 more and more complex, structurally and functionally. Fault diagnosis aims to ensure the safe and stable operation of these systems by detecting and isolating faults as soon as possible (In this paper, ''failure'' and ''fault'' have the same meaning and we use them interchangeably. However, they may have slightly different meanings in some publications). More specifically, fault diagnosis requires to complete three tasks: fault detection, fault isolation, and fault identification, corresponding to determining if a system is running normally, revealing the locations and numbers of faults, and identifying the specific nature of faults, respectively. [2][3][4][5] In real industrial systems, the control of a system can often be implemented by a programmable logic controller (PLC). In general, a PLC consists of a central processing unit, a storage unit, and an input-output unit, and can receive, send and process various electronic signals. A PLC is connected to the sensors distributed on the components of a system such that it can collect the control parameters of the system by reading these sensors. Many existing fault diagnosis approaches in the literature can be implemented with PLCs.
In the domain of DESs, many existing fault diagnosis approaches have two main disadvantages: (i) a number of approaches [6][7][8][9] have exponential computational complexity in the worst case and their computational cost may be prohibitive for large systems and (ii) some approaches [10][11][12] require that any change in sensor readings needs to be treated by a PLC such that the PLC would be too busy processing the changes in sensor readings to perform other tasks.
To overcome these disadvantages, we propose a fault diagnosis approach which equips a system with more sensors and reads sensors at a fixed time interval. The proposed approach has higher computational efficiency and is more appropriate for use in real-world systems with low computing power. On the other hand, the main drawback of the proposed approach is the higher cost of purchasing sensors and the higher difficulty of deploying them.
Differently from the Petri-net-based approach proposed in this paper, some other approaches based on structural analysis 13,14 or fault trees 15,16 are also exposed. In contrast to actively detect and isolate faults in this paper, the stability property of a system is explored in Foroozanfar et al. 17 and Lutz-Ley and Lopez-Mellado. 18 A stable system can automatically return to a normal state from a fault state in finite number of steps. Before presenting the details of the proposed approach, we review some typical publications on fault diagnosis of DES.
Some original theoretical results for fault diagnosis are exposed based on automata. In Sampath et al., 6 a plant is modeled as an automaton in which faults are represented by unobservable events and each observable event is associated with a sensor. A diagnoser for fault diagnosis is constructed offline by an algorithm with exponential complexity. When an event is observed, by inspecting the diagnoser, the fault state of the plant may be one of three cases: faults do not occur, faults may have occurred, and faults must have occurred. This fault diagnosis approach is applied to a realistic HVAC system in Sampath et al. 19 In contrast to automaton models, Petri nets, as a typical mathematical model of DESs, have been widely used in supervisory control, [20][21][22][23] performance optimization, [24][25][26] and model identification 10,11,27,28 because of their intrinsic distributed features and efficiency in handling large systems. Simultaneously, in recent decades, many fault diagnosis approaches based on Petri nets have also been reported, which can be generally categorized into two classes.
In the first class, the sensors are equipped with observable transitions and the output of a system is defined as a sequence of observable transitions. Integer linear programing (ILP) problems often need to be built and solved for performing fault diagnosis. In Dotoli et al., 7 an online fault diagnosis approach is reported that builds an ILP problem based on the observed transition sequence. By assigning two different objective functions to the ILP problem and solving it, whether a fault has occurred can be determined. This approach is extended to the case of labeled Petri net in Fanti et al. 8 and Zhu et al. 29 Basile et al. 30 deal with the fault diagnosis problem by means of the notion of generalized markings, that is, markings in which the number of tokens can be a negative integer. By solving an ILP problem built according to the negative elements of a generalized marking, the occurrence of a fault can be deduced. Wang et al. 31 employ generalized markings to backward conflict-free Petri nets and propose a more efficient fault diagnosis approach by constructing an ILP problem with smaller size.
In Giua and Seatzu, 32 the notion of basis markings is first defined and a fault diagnosis approach based on basis markings is proposed. Given an observed transition sequence, the corresponding basis markings are computed by an algorithm using only algebraic manipulations. The diagnosis result of a fault is obtained by checking the basis markings and, if necessary, solving some ILP problems. The notion of basis markings is further extended to basis reachability graphs in Cabasino et al. 9,33 where a basis reachability graph is first constructed offline and then an online diagnosis algorithm is developed by inspecting the basis reachability graph at each step.
In the second class, the sensors are equipped with observable transitions as well as certain places of a Petri net. The system dynamic is represented as an observable transition sequence or a transition-marking sequence. In Zhu et al., 10,11 faults are described by unobservable transitions not contained in the initial net model of a plant and the output of a system is defined as an observed evolution, that is, a transition-marking sequence. By solving an ILP problem constructed based on the observed evolution, the unobservable transitions are identified that characterize the number and locations of faults.
Ru and Hadjicostis 12 model systems as partially observed Petri nets (i.e. nets equipped with transition and place sensors) and define the system output as an ordered sequence of three tuples (M, t, M 0 )'s, where M and M 0 are two markings and t is a transition. After transforming the partially observed Petri net into a labeled net, they propose an online fault diagnosis algorithm based on reachability graph analysis of the unobservable subnet of the labeled net. The study in Lefebvre 34 also utilizes partially observed Petri nets and provides an efficient fault diagnosis algorithm by solving a number of linear matrix inequalities. The number of times of solving inequalities is linear in the length of an observed sequence.
In Ramirez-Trevino et al., 35 a bottom-up modeling methodology is explored to build an interpreted Petri net (IPN) model of a system. By dividing the set of places into a subset of places modeling fault states and a subset of places modeling normal states, the diagnosability of the built IPN is formally defined and a scheme for detecting and locating fault states is developed. By assuming that all places are observable, Genc and Lafortune 36 extend the diagnoser approach based on automata in Sampath et al. 6 to the context of Petri nets. A Petri net diagnoser is constructed to perform online diagnosis. This approach is of high computational complexity since the marking enumeration upon observing an transition at each step is needed.
The study in Pencole and Subias 37 explores the diagnosability of safe labeled time Petri nets based on the notion of event patterns. An efficient approach of determining diagnosability of a safe Petri net is reported by means of model-checking techniques. Al-Ajeli and Parker propose a fault diagnosis approach for labeled Petri nets based on Fourier-Motzkin elimination. A diagnoser in the form of sets of inequalities is first constructed offline and then online fault diagnosis is performed by checking the constructed diagnoser when observing an event. This approach provides a better trade-off between the size of the diagnoser and diagnosis time. In recent years, some extended versions of fault diagnosis are studied, such as robust diagnosis, 38 diagnosability enforcement, 39 and synchronous diagnosis. 40,41 Two comprehensive surveys on fault diagnosis can be found in Al-Ajeli and Parker 42 and Lafortune et al. 43

Contributions
As already mentioned above, the first class of fault diagnosis approaches often needs to solve ILP problems whose size is linear or polynomial with respect to the length of the observed sequence. When the observed sequence is very long, these approaches become computationally prohibitive. On the other hand, the second class of approaches generally assumes that all or part of places are observable, that is, these places are equipped with sensors. Moreover, the approaches in the second class usually require that any change in the readings of place sensors needs to be treated by a PLC. A Petri net model of a real-world system may include a large number of places and there are a deluge of changes of sensor readings during the operation of the system. The PLC would be too busy processing the changes in sensor readings to perform other tasks. Consequently, in some cases, the existing fault diagnosis approaches are not applicable to real-world systems.
In this paper, we assume that part of transitions and all places are equipped with sensors. In addition, due to the limited processing power of a PLC, we assume that it does not monitor the changes of readings of place sensors all the time, but periodically reads the values of the sensors when needed. The system output is defined as a marking sequence interleaved with possible observed transitions.
Based on the observed system output, a fault diagnosis algorithm is developed by defining and solving ILP problems whose size is regardless of the length of the system output. Thus, the computational cost of the algorithm will not increase with the increase of the length of the system output. Namely, the algorithm enjoys a high computational efficiency for those systems that satisfy the assumptions made in this paper. On the other hand, since the PLC only requires to read place sensors once in a time period and does not monitor the changes of sensor-readings all the time, the proposed algorithm is more suitable for fault diagnosis of some PLC-based systems.
This paper is organized as follows. In Section 2, some basic definitions on Petri net are provided. In Section 3, the problem to be addressed is formally defined and a solution to the problem is reported in Section 4. In Section 5, we extend the fault diagnosis algorithm for Petri nets to the case of labeled Petri nets. To show the effectiveness of the proposed approach, in Section 6, we apply the approach to a case study example. Finally, a conclusion is drawn in Section 7.

Basic definitions
In this section, we introduce the definitions and notations used throughout the paper. For the complete details of Petri nets, the reader is referred to Giua and Silva 44 and Murata. 45 A Petri net is a bipartite graph represented as a four-tuple N = (P, T, Pre, Post), where P is a set of m places, T is a set of n transitions with P [ T 6 ¼ ; and P \ T = ;, Pre : P3T ! N (N is the set of nonnegative integers) and Post : P3T ! N are two functions represented as two matrices, which specify the arcs of the graph. We denote by C = PostÀPre the incidence matrix of net N. The sets of input places and of output places of a transition t are denoted by t = fp 2 PjPre(p, t) . 0g and t = fp 2 PjPost(p, t) . 0g, respectively. Similarly, for a place p 2 P, we define p = ft 2 TjPost(p, t) . 0g and p = ft 2 TjPre(p, t) . 0g.
A marking of a Petri net is a mapping M : P ! N. The number of tokens in a place p 2 P at a marking M is represented by M(p). A marking M = ½x 1 , . . . , x m T is written as M = x 1 p 1 + Á Á Á + x m p m (the items whose coefficients are zero are omitted) for simplicity. By associating a Petri net N with an initial marking M 0 , a Petri net system hN, M 0 i is defined.
A transition t 2 T is said to be enabled at marking M, denoted by M ½ti, if the number of tokens in each input place of t is greater or equal to the weight of the corresponding arc, that is, M(p)5Pre(p, t) for all p2 t: With a slight abuse of notation, we use M½si to denote that a transition sequence s 2 T Ã is enabled at marking M: A marking M a is reachable from M after firing s, denoted by M½siM a . In addition, M a is computed by the state equation of a net where p is a function, defined by p : T Ã ! N n , which computes the Parikh vector of a transition sequence s. If a transition t is in s, we write t 2 s for simplicity. The set of transition sequences that are enabled at the initial marking M 0 is defined as The reachability set, represented as R(N, M 0 ), of a net system contains all markings that are reachable from M 0 by firing a transition sequences s 2 L(N, M 0 ), that is, R(N, M 0 ) = fM 2 N m j(9s 2 T Ã )M 0 ½siMg: A transition is said to be observable if it is equipped with a sensor that monitors its firing; otherwise, it is called unobservable. We denote by T o and T u the set of observable transitions and the set of unobservable transitions, respectively. In addition, the cardinalities of T o and T u are represented as n o and n u , respectively. Thus, the set T of transitions is partitioned into two disjoint subsets T o and T u with T = T o [ T u . A place of a Petri net is said to be measurable if the number of tokens residing into it can be detected by a sensor. In this paper, we assume that all places of a Petri net are measurable. A Petri net is said to be acyclic if it does not contain any directed cycle. respectively.
According to Def. 1, it is straightforward to obtain the T u -induced subnet of N = (P, T, Pre, Post), denoted by N u = (P, T u , Pre u , Post u ). We also call the T u -induced subnet the unobservable subnet of N. The incidence matrix of N u is represented by C u = Post u À Pre u . Unless otherwise stated, the unobservable subnet of the considered Petri nets in this paper is assumed to be acyclic.
To characterize failures in a real-world system, the unobservable transitions in T u are further divided into regular unobservable transitions, denoted by T reg , and fault transitions, denoted by T f , that is, T u = T reg [ T f and T reg \ T f = ;. The fault transition set T f is partitioned into r fault classes, that is, [ T r f , and the partition is represented as P f = fT 1 f , . . . , T r f g. For simplicity, we say that T i f occurs if a fault f 2 T i f takes place in a system. Given a sequence s 2 T Ã , we use t 2 s to denote that t is contained in s and T i f 2 s to denote that there exists at least a transition f 2 T i f such that f 2 s. A Petri net system with a labeling function l : T [ feg ! E [ feg is called a labeled Petri net (LPN) system, denoted by hN, M 0 , E, li, where E is an alphabet and e represents the empty string. The label of the empty string e is itself, that is, l(e) = e. The set of transitions that have the same label e is denoted by T e = ft 2 Tjl(t) = eg. The labeling function l is extended to a transition sequence s = t 1 t 2 . . . t h 2 T Ã with h being its length by defining l(s) = l(t 1 )l(t 2 ) . . . l(t h ). We obtain the underlying Petri net of an LPN by removing all labels of transitions of the LPN.

Problem definition
In general, faults in a system can be divided into three types: incipient, intermittent, and permanent. The approach proposed in this paper is based on Petri nets (a typical discrete event model) and are appropriate for faults that cause a distinct change in the state of system components but do not necessarily bring the system to a halt. Thus, the proposed approach can be used to detect intermittent or permanent faults. These faults may originate from different system components, such as sensors, actuators, or controllers.
The problem of fault diagnosis consists in determining whether faults have occurred according to the behavior of a system. In general, the behavior of a system is described by its output, that is, sensor-readings at each step during the system evolution.
This paper deals with the fault diagnosis problem of PLC-based Petri nets. Though all places of the considered net are measurable, we assume that a PLC does not monitor the changes of readings of place sensors all the time due to the limited processing power of the PLC. To define the output of a Petri net system, the following assumptions hold for the systems under consideration: (A1) Reading place sensors and firing any transition can be done instantly. (A2) Place sensors are read once in K time units.
In a real PLC-controlled system, reading sensors is usually implemented by a hardware interrupt and performing an action (i.e. firing a transition) is usually carried out by a callback function of programing languages. In this way, the controller of the system can know if the operation of reading sensors or performing an action is successful and obtain the corresponding sensor data if the answer is positive. However, in this paper, we mostly focus on the logic steps of a fault diagnosis algorithm, without explicitly considering its software implementation. Thus, we make Assumption (A1) for the convenience of discussion. Simultaneously, we make Assumption (A2) to avoid a situation that the PLC of a system is too busy processing the changes of readings of place sensors to perform other tasks.
On the basis of Assumptions (A1) and (A2), the output of a system at each step is represented by two possible cases: In the first case, M 0 is reachable from M by firing an unobservable transition sequence s u 2 T Ã u , that is, M½s u iM 0 , and M 0 is obtained by reading place sensors after K time units from the starting point M.
In the second cases, starting from M, an observable transition t o fires before reaching K time units and the output is represented as (M, t o , M 0 ) satisfying M½s u iM a ½t o iM 0 , where s u 2 T Ã u and M a 2 R(N, M 0 ). Namely, marking M a is reached from M by firing an unobservable transition sequence. After observing transition t o , the timer is reset to zero and the elapsed time units are recounted. Subsequently, we provide an example to clarify this. Example 1. Consider the Petri net shown in Figure 1, If the time interval to read place sensors is four time units (i.e. K = 4), then a possible evolution of the net is shown in Figure 2. The timeline shows the moments to read place sensors. The output sequence obtained along this timeline is represented as a marking-transition sequence, that is, and (M 4 , M 5 ), as shown in the lower part of Figure 2.
In Step 1, from the starting point M 0 , no observable transition is observed during four time units. Then, at the fourth time unit, place sensors are read and the marking M 1 = p 2 + p 3 is obtained. Thus, the output in Step 1 is the first case mentioned above, that is, a marking pair (M 0 , M 1 ). In Step 2, a timer restarts from marking M 1 and we observe transition t 1 before four time units elapse. In addition, by reading place sensors, the reached marking after firing t 1 is M 2 = p 3 + p 4 . Thus, the output in Step 2 can be represented as the second cases defined previously, that is, a three tuple (M 1 , t 1 , M 2 ). The outputs in Steps 3-5 can be similarly explained and are illustrated in Figure 2. r Definition 2. A trace of a Petri net system hN, The set of traces of a net system hN, M 0 i is defined as T (N , M 0 ) = fsjis a traceg: Obviously, the output sequence of a Petri net in this paper, defined under Assumptions (A1) and (A2), is a trace. For example, the output sequence, say s 1 , in Example 1 is a trace and it holds s 1 2 T (N, M 0 ). Now, we are ready to formally define the fault diagnosis problem addressed in this paper.   Output sequence Step 1 Step 2 Step 3 Step 4 Step Example 2. By specifying T 1 f = ff 1 , f 4 g and T 2 f = ff 2 , f 3 g, let us consider the Petri net shown in Figure 1 again. Consider two markings M 0 = p 1 + p 2 and M 1 = p 2 + p 3 as shown in Figure 2. Figure 3 is a part of the reachability graph, describing all possible paths from M 0 to M 1 that contain unobservable transitions only.
It is easy to verify that there are four paths from M 0 to M 1 , as shown in the following: Since It is not realistic to compute diagnosis decision of each fault class via reachability graph analysis because of the state explosion problem. we next provide a linear algebraic characterization of all possible unobservable transition sequences from one marking to another.
For two markings M, M 0 2 R(N, M 0 ) and a fault class T i f 2 P f , we construct the following two ILP problems where y is a non-negative integer vector of n u -dimension. The item P   In Def. 6, we observe that the global diagnoser of a trace s can be computed by inspecting all local diagnosers of steps in the trace. Next, we develop an algorithm to detect faults that have occurred till the observation of a trace.
The main logical flow of Algorithm 1 is illustrated by the flowchart shown in Figure 5. More specifically, in Line 1, the global diagnoser Y is initialized to an rdimensional column vector Y =0 r 2 f0, 1, 2g r such that The main computational cost of Algorithm 1 stems from the solution of ILPP 1 and/or ILPP 2. It is well known that the complexity of an integer linear programing problem is NP-complete and is closely related to its size (i.e. the numbers of unknown variables and constraints). However, in practice, many integer linear programing problems can be efficiently solved using commercial solvers (such as Gurobi Solver 46 used in the paper). Since integer linear programing problems ILPP 1 and ILPP 2 have the same size, we analyze the size of ILPP 1 only. The number of unknown variables is denoted by where n u is the number of unobservable transitions; the number of constraints is denoted by where m is the cardinality of place set. We observe that the size of ILPP 1 is regardless of the length L of a trace s. In plain words, if we observe a labeled trace v, the underlying evolution of a system is a trace s such that l(b i ) = e i with i = 1, . . . , L. We use e i M i 2 v to denote that e i M i is contained in v, i 2 f1, . . . , Lg. To conveniently present the fault diagnosis algorithm for LPNs, we define the following operator.
Given a labeled trace v, there often exist multiple traces s's that have the same observation. We use the operator to combine the diagnosis decisions of these traces to form the diagnosis result of the labeled trace. Algorithm 2 illustrates the usage of . Before present the algorithm, we define an ILP problem:    Case study In this section, we show the application and computational efficiency of the proposed approach by means of a plant example. Let us consider the plant shown in Figure  8, which contains five machines (M1-M5), four robotic arms (R1-R4), two buffers with capacity 4 (B1 and B2), two entrances (I1 and I2), two exits (O1 and O2), and two automatic guided vehicles (AGV1 and AGV2). This plant has two production lines, as shown by the left part and right part of Figure 8, respectively: In production line 1 (i.e. the left part of Figure  8), robotic arm R1 first takes a raw part from entrance I1 and then load it into machine M1 or M2. After machine M1 or M2 finishes processing the part, robotic arm R3 unloads the part and puts it into buffer B1. When buffer B1 is not empty, R3 takes a part from B1 and loads it into machine M3. Robotic arm R2 unloads the finished part from M3 and puts it into AGV1 that transfers the part to exit O1.
In production line 2 (i.e. the right part of Figure  8), robotic arm R1 takes a raw part from entrance I2 and loads it into machine M4. Robotic arm R4 unloads the processed part from M4 and puts it into buffer B2. When B2 is not empty, R4 takes a part from B2 and puts it into machine M5. Robotic arm R2 takes the finished part from M5 and puts it into AGV 2. Finally, the part is transferred to exit O2 by AGV 2.
Each production line contains nine events, as indicated by the numbers 1-9 in Figure 8. The Petri net model of the plant is shown in Figure 9. Nine events of production line 1 and their corresponding transitions in Figure 9 are demonstrated in Table 2. The events of production line 2 and the corresponding transitions can be analogously explained. Apart from the events in each production line, the components (machines, robotic arms, etc.) of the plant shown in Figure 8 are also explicitly characterized by the places of the Petri net model shown in Figure 9, as listed in Table 3.
We assume that there are two failures in the plant, which are described by two fault transitions f 1 and f 2 in Figure 9, respectively. Transition f 1 characterizes a failure that a part is stored into buffer B1 before being machined by machine M1 and f 2 describes that a part is directly processed by machine M5 before being stored into buffer B2.
In this case study, we compare the computational efficiency of the proposed approach with the ones in Fanti et al. 8 and Zhu et al. 29 by following the steps below: Step 1: Simulate the operation of the net system shown in Figure 9 and generate an evolution, that is, a sequence that records all reached markings and fired transitions in order.
Step 2: Compute three observations of the evolution generated in Step 1, which correspond to this paper Fanti et al. 8 and Zhu et al, 29 respectively.
Step 3: Run the diagnosis algorithms proposed in this paper, 8,29 respectively, by taking as input the corresponding observation, and record the running time at each step of the observation.

The generated evolution in
Step 1 is shown in Figure  10. For this paper, the corresponding observation of the evolution is demonstrated in Figure 11, which is represented as v 1 = M 0 e 1 M 1 e 2 M 2 . . . e 31 M 31 .  Table 3. Explanations of some places of the net shown in Figure 9. Meanwhile, for the approaches in Fanti et al. 8 and Zhu et al., 29 the observation of the evolution is v 2 = aaabcdgdbdgaaabcbcdddgaccddg, that is, these two approaches have the same observation. Since the length of v 2 is 28 and the approaches in Fanti et al. 8 and Zhu et al. 29 use an online manner to perform diagnosis, we take v 0 1 = M 0 e 1 M 1 . . . e i M i with i = 1, . . . , 28 as an input of Algorithm 2 in turn.
The running times of these three algorithms when observing a step of the corresponding observation are shown in Tables 4 and 5, which are tested on a laptop with Intel Core i7-1165G7 processor and 16G RAM using Gurobi Solver (academic license). 46 The relationship of running times of these three approaches in each step is visualized in Figure 12.
We observe that the running times of the approaches in Fanti et al. 8 and Zhu et al. 29 significantly increase as the increase of the length of the observation. The main reason for such a situation is that the size of the ILP problems built in Fanti et al. 8 and Zhu et al. 29 is linear with the length of an observation. However, the size of the ILP problem constructed in this paper is regardless of the length of an observation, as indicated by equations (6) and (7). Thus, the running time of our approach in each step remains basically the same and does not quickly increase when the observation becomes longer. In this case study, our approach is more efficient in contrast to the ones in Fanti et al. 8 and Zhu et al. 29 Figure 10. An evolution recording all reached markings and fired transitions in order. Figure 11. The observation of the evolution shown in Figure 10 in this paper. Table 4. Running times (in second) for steps 1-14. Step

Conclusion
In this paper, we solve the fault diagnosis problem using Petri net models. Two fault diagnosis algorithms for Petri nets and LPNs are developed, respectively. The proposed approach enjoys higher computational efficiency compared with those in Fanti et al. 8 and Zhu et al. 29 and is more suitable for use in real-world systems with low computing power. Future works are twofold. Firstly, we plan to employ the proposed approach to a real-world system and report its effectiveness. Secondly, the proposed approach will be extended to stochastic Petri nets by associating a firing probability with each transition.

Declaration of conflicting interests
The author(s) declared no potential conflicts of interest with respect to the research, authorship, and/or publication of this article. Running time (s) ref. [4] ref. [25] this paper Figure 12. Comparison of approaches in this paper Fanti et al. 8 and Zhu et al. 29