ࡱ>       5@ ibjbj22 ,QXX'3LLLL(((<hhh8Dl<<< "`߶xRʼh(!^LLCI1I1I1LV(߶I1߶I1I1[2^S(s yh +hö 0<2#x ľs<<LLLLľ(sPI1< I1<  Universal Plug and Play Machine Models U. Glsser, Y. Gurevich and M. Veanes {glaesser, gurevich, margus}@microsoft.com June 15, 2001 Technical Report  FILLIN \* MERGEFORMAT MSR-TR-2001-59 Microsoft Research Microsoft Corporation One Microsoft Way Redmond, WA 98052 Abstract Recently, Microsoft took a lead in the development of a standard for peer-to-peer network connectivity of various intelligent appliances, wireless devices and PCs. It is called the Universal Plug and Play Device Architecture (UPnP). We construct a high-level Abstract State Machine (ASM) model for UPnP. The model is based on the ASM paradigm for distributed systems with real-time constraints and is executable in principle. For practical execution, we use AsmL, the Abstract state machine Language, developed at Microsoft Research and integrated with Visual Studio and COM. This gives us an AsmL model, a refined version of the ASM model. The third part of this project is a graphical user interface by means of which the runs of the AsmL model are controlled and inspected at various levels of detail as required for e.g. simulation and conformance testing.  TOC \o "1-3" \h \z \u  HYPERLINK \l "_Toc517177085" 1 Introduction  PAGEREF _Toc517177085 \h 3  HYPERLINK \l "_Toc517177086" 2 The UPnP Protocol  PAGEREF _Toc517177086 \h 4  HYPERLINK \l "_Toc517177087" 2.1 Basic Properties  PAGEREF _Toc517177087 \h 4  HYPERLINK \l "_Toc517177088" 2.2 Sample UPnP Device  PAGEREF _Toc517177088 \h 5  HYPERLINK \l "_Toc517177089" 3 Abstract State Machine Model  PAGEREF _Toc517177089 \h 6  HYPERLINK \l "_Toc517177090" 3.1 Distributed Real-Time ASM  PAGEREF _Toc517177090 \h 6  HYPERLINK \l "_Toc517177091" 3.1.1 Components and Interfaces  PAGEREF _Toc517177091 \h 7  HYPERLINK \l "_Toc517177092" 3.1.2 Abstract Data Structures  PAGEREF _Toc517177092 \h 8  HYPERLINK \l "_Toc517177093" 3.1.3 TCP/IP Network and Protocols  PAGEREF _Toc517177093 \h 9  HYPERLINK \l "_Toc517177094" 3.1.4 Basic Agent Types  PAGEREF _Toc517177094 \h 9  HYPERLINK \l "_Toc517177095" 3.1.5 Discrete Time and Timeout Events  PAGEREF _Toc517177095 \h 10  HYPERLINK \l "_Toc517177096" 3.2 Addresses and Messages  PAGEREF _Toc517177096 \h 11  HYPERLINK \l "_Toc517177097" 3.2.1 Addresses  PAGEREF _Toc517177097 \h 11  HYPERLINK \l "_Toc517177098" 3.2.2 Representation of Messages  PAGEREF _Toc517177098 \h 12  HYPERLINK \l "_Toc517177099" 3.2.3 Sending and Receiving Messages  PAGEREF _Toc517177099 \h 12  HYPERLINK \l "_Toc517177100" 3.3 Abstract Protocol Model  PAGEREF _Toc517177100 \h 13  HYPERLINK \l "_Toc517177101" 3.3.1 Initial States  PAGEREF _Toc517177101 \h 13  HYPERLINK \l "_Toc517177102" 3.3.2 Network Model  PAGEREF _Toc517177102 \h 13  HYPERLINK \l "_Toc517177103" 3.3.3 Device Model  PAGEREF _Toc517177103 \h 15  HYPERLINK \l "_Toc517177104" 4 Executable Protocol Model and GUI  PAGEREF _Toc517177104 \h 17  HYPERLINK \l "_Toc517177105" 4.1 Gaphical User Interface  PAGEREF _Toc517177105 \h 17  HYPERLINK \l "_Toc517177106" 4.2 Executable Protocol Model  PAGEREF _Toc517177106 \h 19  HYPERLINK \l "_Toc517177107" 4.3 Communication Model  PAGEREF _Toc517177107 \h 20  HYPERLINK \l "_Toc517177108" 4.3.1 IP Address Space  PAGEREF _Toc517177108 \h 20  HYPERLINK \l "_Toc517177109" 4.3.2 Representation of Messages  PAGEREF _Toc517177109 \h 20  HYPERLINK \l "_Toc517177110" 4.3.3 Sending and Receiving Messages  PAGEREF _Toc517177110 \h 21  HYPERLINK \l "_Toc517177111" 4.4 Network Model  PAGEREF _Toc517177111 \h 22  HYPERLINK \l "_Toc517177112" 4.4.1 RunNetwork  PAGEREF _Toc517177112 \h 22  HYPERLINK \l "_Toc517177113" 4.4.2 DHCP Server  PAGEREF _Toc517177113 \h 22  HYPERLINK \l "_Toc517177114" 4.5 Control Point Model  PAGEREF _Toc517177114 \h 23  HYPERLINK \l "_Toc517177115" 4.5.1 Search for Devices  PAGEREF _Toc517177115 \h 23  HYPERLINK \l "_Toc517177116" 4.5.2 Processing Ads  PAGEREF _Toc517177116 \h 24  HYPERLINK \l "_Toc517177117" 4.5.3 Controlling Devices  PAGEREF _Toc517177117 \h 24  HYPERLINK \l "_Toc517177118" 4.6 Device Model  PAGEREF _Toc517177118 \h 25  HYPERLINK \l "_Toc517177119" 4.6.1 Addressing  PAGEREF _Toc517177119 \h 25  HYPERLINK \l "_Toc517177120" 4.6.2 Discovery  PAGEREF _Toc517177120 \h 27  HYPERLINK \l "_Toc517177121" 4.6.3 Description  PAGEREF _Toc517177121 \h 28  HYPERLINK \l "_Toc517177122" 4.6.4 Presentation  PAGEREF _Toc517177122 \h 28  HYPERLINK \l "_Toc517177123" 4.6.5 Eventing  PAGEREF _Toc517177123 \h 28  HYPERLINK \l "_Toc517177124" 4.6.6 Control  PAGEREF _Toc517177124 \h 28  HYPERLINK \l "_Toc517177125" 4.6.7 SERVICE Interface  PAGEREF _Toc517177125 \h 29  HYPERLINK \l "_Toc517177126" 5 Conclusions  PAGEREF _Toc517177126 \h 29  HYPERLINK \l "_Toc517177127" Acknowledgements  PAGEREF _Toc517177127 \h 30  HYPERLINK \l "_Toc517177128" References  PAGEREF _Toc517177128 \h 30  HYPERLINK \l "_Toc517177129" 6 Appendix I: AsmL model of CD Player  PAGEREF _Toc517177129 \h 31  HYPERLINK \l "_Toc517177141" 7 Appendix II: IServer Interface  PAGEREF _Toc517177141 \h 43  Introduction The group on Foundations of Software Engineering at Microsoft Research has developed a powerful specification language based on the notion of Abstract State Machines (ASMs) [ REF _Ref513622890 \r \h 4]. The language is called AsmL, the Abstract state machine Language [ REF _Ref509910336 \r \h 9]. AsmL is executable. Furthermore, it is integrated with Microsoft software development environment including Visual Studio and COM, Component Object Model [ REF _Ref515906955 \r \h 13]. AsmL supports specification and rapid prototyping of object oriented and component oriented software. The main strength of ASMs in general and AsmL in particular is the precise, rigorously defined semantics. ASMs have been used to specify architectures, protocols, modeling languages, programming languages, and so on [ REF _Ref515900017 \r \h 10]. In particular, the International Telecommunication Union (ITU) recently approved an ASM-based formal semantics definition of SDL, the Specification and Description Language of ITU, as an official ITU-T standard [ REF _Ref515900185 \r \h 11]. AsmL was developed in order to deploy the ASM technology for industrial software development, in particular at Microsoft; see [ REF _Ref515901015 \r \h 12] for an overview. Recently, Microsoft took a lead in the development of a standard for peer-to-peer network connectivity of various intelligent appliances, wireless devices and PCs. The current version of the standard is Universal Plug and Play (UPnP) Device Architecture V 1.0 defined in [ REF _Ref509291474 \r \h 1]; see also the website [ REF _Ref515900839 \r \h 2] of the UPnP Forum. Based on[ REF _Ref509291474 \r \h 1], we present in this document a high-level, executable ASM model of the protocol underlying the UPnP architecture. The model is concurrent, interactive, and real-time dependent. Here is how UPnP is described in[ REF _Ref509291474 \r \h 1]: Universal Plug and Play is a distributed, open networking architecture that leverages TCP/IP and the Web technologies to enable seamless proximity networking in addition to control and data transfer among networked devices in the home, office and public spaces. This paper is a part of a larger study of distributed systems. Starting from an informal specification, like the UPnP standard, we construct a hierarchy of executable mathematical models called Abstract State Machines or ASMs.In this case, we construct two ASMs, a higher-level ASM described in Section  REF _Ref516565833 \r \h 3, and a lower-level AsmL in Section  REF _Ref516565819 \r \h 4. We cover most of the UPnP definition; there are no conceptual difficulties in covering the remainder. What are executable mathematical models good for? Unlike traditional engineering disciplines, like mechanical or electrical engineering, systems engineering heavily relies on informal documentation. Such informal documentation is necessary and, as in the case of the UPnP definition, may be informative and useful. Still, informal documentation is informal and thus may be and often is ambiguous, incomplete, and even inconsistent. Properly constructed, mathematical models are consistent, avoid unintended ambiguity and are complete in the appropriate sense.Certain properties of the design can be proved mathematically. Furthermore, in contrast with informal documentation, our mathematical models are executable and so they can be used to explore and test the design. You can validate your models and generate test suites for conformance testing of your implementation. Let us emphasize that our mathematical models build on the given informal description. We fix loose ends, resolve ambiguities and inconsistencies, separate concerns, and so on. Gradually the given informal description gives rise to an executable mathematical model or to a hierarchy of such models. In this paper, we concentrate on interoperability aspects rather than details of individual components. Components operate concurrently and interact with each other by exchanging messages over the communication network. They use actuators and sensors to interact with the external world, which is the environment into which the whole system is embedded. The ASM paradigm allows us to combine synchronous as well as asynchronous computations. The component models themselves are parallel compositions of synchronously operating ASMs. The system as a whole is a composition of asynchronously operating components, called agents. The Document Structure. Section  REF _Ref516021994 \r \h 2 gives a brief overview of the UPnP protocol and illustrates a sample UPnP device. In Section  REF _Ref513632444 \r \h 3 we introduce the higher-level UPnP machine model in several steps. In  REF _Ref510511786 \r \h 3.1 we explain its overall structure and characteristic features, the underlying notions of concurrency and time, and its main components and interfaces. In  REF _Ref513633309 \r \h 3.2 we define the basic communication primitives and data structures. In  REF _Ref511019085 \r \h 0 we define the behavior model. In Section  REF _Ref516565819 \r \h 4 we introduce the lower-level protocol model in AsmL and illustrate the tool environment for simulating the AsmL model. We start by treating basic properties of addressing and communication (Section  REF _Ref511019672 \r \h 4.3). Next, we define the individual component models, namely: the network model(Section  REF _Ref511019765 \r \h 4.4), the control point model (Section  REF _Ref513542702 \r \h 4.5) and the device model (Section  REF _Ref511019816 \r \h 4.6). Conclusions are presented in Section  REF _Ref510582540 \r \h  \* MERGEFORMAT 5. Appendix I contains a detailed AsmL model of the sample UPnP device that is briefly described in Section  REF _Ref512138262 \r \h 0. Remark. This document is available in electronic form that allows automatic code extraction for feeding the AsmL compiler [ REF _Ref509910336 \r \h 9]. The AsmL parts are marked by a special document style so that they can easily be identified within the document. The UPnP Protocol In the given application context, we attempt to accurately reflect the abstraction level of the informal description of the UPnP Device Architecture as defined in [ REF _Ref509291474 \r \h  \* MERGEFORMAT 1]. Nonetheless, one wants to abstract from those details that are irrelevant for the understanding of the principle protocol behavior. To figure out what is relevant and what can be neglected is often not trivial and sometimes impossible without consulting the application domain experts. In our case these experts are the UPnP developers at Microsoft. Basic Properties We briefly summarize here basic characteristics of the UPnP architecture. Technically, this is a layered protocol architecture built on top of TCP/IP networks by combining various standard protocols, e.g. such as DHCP, SSDP, SOAP and GENA. It supports dynamic configuration of any number of devices offering services requested by control points. To perform certain control tasks, a control point needs to know what devices are available (i.e. reachable over the network) and what services these devices advertise. For a concrete example of a UPnP device see Section  REF _Ref516053232 \r \h 2.2. Restrictions. In general, the following restrictions apply: Devices may come and go at any time with or without prior notice. Consequently, there is no guarantee that a requested service is available in a given state or will become available in a future state. An available service may not remain available until a certain control task using this service has been completed. Control points and devices interact through exchange of messages over a TCP/IP network, where specific network characteristics (like bandwidth, dimension, reliability) are left unspecified. As such, communication is considered to be neither predictable nor reliable, i.e. message transfer is subject to arbitrary and varying delays, and certain messages may even get lost. Basic Steps. The UPnP protocol defines 6 basic steps or phases. Initially, these steps are invoked one after the other in the order given below, but may arbitrarily overlap afterwards. Step 0: Addressing is needed for obtaining an IP address when a new device is added to a network. Step 1: Discovery informs control points about the availability of devices and their service. Step 2: Description allows control points to retrieve detailed information about a device and its capabilities. Step 3: Control provides mechanisms for control points to access and control devices through well-defined interfaces. Step 4: Eeventing allows control points to receive information about changes in the state of a service at run time. Step 5: Presentation enables users to retrieve information about a device as needed by for controlling the device. Sample UPnP Device As an example we consider a CD player [ REF _Ref515900839 \r \h  \* MERGEFORMAT 2]. In our model this device has two services, called ChangeDisc, PlayCD, where Figure 1 illustrates only the first one. The ChangeDisc allows a control point to add or remove discs from the CD player and to choose a disc to be placed on the tray. The complete service has the following basic actions (not requiring any arguments). AddDisc NextDisc PrevDisc RandomDisc OpenDoor CloseDoor ToggleDoor HasTrayDisc IsDoorOpen The PlayCD service has the following actions. Play Pause Stop SetPlayProgram ONCE_RANDOM (or REPEAT_RANDOM or REPEAT_IN_ORDER) SelectTrack number NextTrack PrevTrack The full AsmL model of the CD Player with these two services is given in Appendix I.  Figure 1: ChangeDisc service of a CD Player Abstract State Machine Model This section describes our ASM model of UPnP and the rational behind. The ASM model serves as a conceptual framework for dealing with system behavior at a more abstract level; nevertheless, it is closely related to the executable AsmL version, as described in Section  REF _Ref516565819 \r \h 4, so that the translation into the latter becomes obvious. Conceptually, the ASM model is designed to meet two fundamental requirements on technical descriptions of complex software systems, namely: robustness provides the flexibility needed to extend and modify the model with a reasonable effort, simplicity avoids formalization overhead by stating behavior at the given level of abstraction, i.e. reflecting the view of the informal description. Technically speaking, the model classifies as distributed real-time ASM and as such is based on fairly general notions of concurrency and time. Aiming at an intuitive understanding, we explain the underlying mathematical concepts in a rather informal style concentrating on those aspects that are relevant here. For a rigorous mathematical definition of the theory of Abstract State Machines, see the original literature [ REF _Ref509992898 \r \h  \* MERGEFORMAT 3, REF _Ref510239397 \r \h  \* MERGEFORMAT 5]. Distributed Real-Time ASM A reasonable choice for the construction of an abstract UPnP protocol model is a distributed real-time ASM consisting of an arbitrary number of concurrently operating and asynchronously communicating components. Intuitively, a component either represents a device, a control point or some fraction of the underlying communication network. With each component type we associate one or more interfaces such that any interaction between a component and any other component is restricted to actions and events as observable at these interfaces. Furthermore, actions and events in the external world as represented by the environment into which the system under consideration is embedded may affect the system behavior in various ways. For instance, the transport of messages over the communication network is subject to delays and some messages may even get lost. Also, the system configuration itself may change as devices come and go. Such actions and events are basically unpredictable. We therefore introduce an additional GUI (cf. Section  REF _Ref517204509 \r \h 4.1) that allows for user-controlled interaction with the external world. The overall organization of the model is illustrated in Figure 2.  Figure 3: Overall organization of the distributed ASM model of UPnP. At the component level, control points and devices are further decomposed, where each individual component splits into a collection of synchronously operating functional units. This decomposition is such that each of the resulting units participates in a different protocol step (cf. Section  REF _Ref516463488 \r \h 2.1). Accordingly, we model control points and devices as parallel compositions of synchronously operating ASMs. For dealing with real-time constraints, we introduce a discrete notion of time for the abstract representation of global system time. In particular, we model timeout events through timer mechanisms (Section  REF _Ref515953682 \r \h 0). Components and Interfaces We formulate dynamic properties of the UPnP protocol in terms of component interactions. Components operate autonomously and so that we can identify them with ASM agents in the distributed ASM. Agents come as elements of a dynamically growing and shrinking universe (or domain) AGENT, where we associate with each agent a program defining its behavior. A program consists of guarded update rules specifying state transitions through local updates on global states. We distinguish different types of agents according to different types of programs as represented by a static universe PROGRAM. domain AGENT, static domain PROGRAM In any given state of an ASM run, the behavior of an agent is well defined as stated by a unary dynamic function program. Being dynamic, this function allows introducing new agents at run time. program : AGENT ( PROGRAM, forall a ( AGENT: program(a) ( PROGRAM Any interaction between the model and the external world, as observable at the respective interfaces, is reduced to interaction between two different categories of agents: (1) explicitly defined agents of the model, and (2) implicitly given agents of the environment. The non-deterministic nature of environment agents naturally reflects the system view of the environment. However, this does not mean that environment behave in a completely unpredictable way; rather one can formulate reasonable integrity constraints on external actions and events where appropriate. Roughly, one can characterize the model through the following basic properties: Initial State: An initial state specifies some finite collection of agents, which may grow and shrink dynamically over an ASM run. ASM Agents: There are three types of explicit agents, namely: control point agents, device agents and network agents. Concurrency: Agents operate concurrently. They interact by reading and writing shared locations of globally shared system states. The underlying semantic model regulates interaction between agents so that potential conflicts are resolved according to the definition of partially ordered runs [ REF _Ref513622890 \r \h 4]. Instantaneous Reactions: Agents react instantaneously, i.e. they fire their rules as soon as they reach a state in which the rules are enabled. (Strictly speaking, one must assume here some non-zero delay to preserve the causal ordering of actions and events; though, this delay is immaterial from an application point of view.). Atomicity: Computation steps of agents are atomic, but, nevertheless, are considered as time-consuming actions. Discrete Time: System time is based on a discrete notion of time with time values being represented as real numbers. Abstract Data Structures In order to simplify modeling and to stay close to the informal understanding, we assume the presence of a rich background structure. In particular, we will be using sets and maps in our model. We may have sets of integers, maps from integers to strings, or even sets of such maps, etc. Both maps and sets may be viewed as aggregate entities and may be updated point-wise. For example, if s is a set of integers, s : Set of Integer say s is {1,2} in the current state then we may update s by firing the following parallel update in order to remove 2 from s and to add 3 to s. s(2) := false s(3) := true In the state resulting from firing this rule, the value of s is {1,3}. If m is a map from integers to integers, m : Map of Integer to Integer that maps 2 to 3 and 4 to 5, then we may update m so that it maps 4 to 6 by firing the rule m(4) := 6 We also have dynamic functions whose range consists of maps. For example, we may have a unary dynamic function f from integers to maps from integers to integers. f : Integer ( Map of Integer to Integer If in the current state f(1) is a map from 2 to 3 and 4 to 5, in symbols f(1)(2)=3 and f(1)(4)=5, then we may update f (1) to map 4 to 6, just as we did with m above, by firing the rule f(1)(4) := 6 Justification for the aggregate view of maps and sets in terms of standard ASMs is given in [ REF _Ref517004973 \r \h 15]. TCP/IP Network and Protocols To model the network behavior, we define an abstraction of TCP/IP networks using standard network terminology [ REF _Ref509221210 \r \h  \* MERGEFORMAT 7]. Our network model is based on a distributed execution model reflecting the fact that a TCP/IP network usually consists of a (not further specified) collection of interconnected physical networks. However, we abstract here from topological details, e.g. how a global network is formed by interconnecting local networks using routers (or gateways); rather we describe the overall network behavior through a collection of concurrently operating communicators, each of which refers to some local network in conjunction with its adjacent routers. Conceptually, we separate behavior of the network and its routers (or gateways) from behavior of the hosts attached to this network as illustrated in Figure 2.  Figure 4: Communicators. Based on the two standard transport level protocols, UDP (User Datagram Protocol) and TCP (Transmission Control Protocol), user level processes, or application programs, interact with each other by exchanging messages over the network. According to this view, there may be several application programs running on a single host. The address of an application program is given by the IP address of its host in conjunction with a unique protocol port number on this host. In our case, several control point programs may run on the same host. Devices, however, are considered as individual hardware units; therefore they are identified with the hosts on which they run. Collectively, we refer to control points and devices as applications. Basic Agent Types This section introduces various domains identifying the basic types of agents and gives an overview on how they are related with each other. We start with the main objects, namely: communicators, control points and devices. domain COMMUNICATOR, domain CONTROL(POINT, domain DEVICE DHCP Server Interface. The Dynamic Host Configuration Protocol (DHCP) enables automatic configuration of IP addresses when adding a new host to a network [ REF _Ref511556901 \r \h 8]. We model interaction between a DHCP server and the DHCP client of a device explicitly only as far as the device side is concerned (cf. Section  REF _Ref513364892 \r \h 3.3.3). The server side is abstractly represented through one or more external DHCP server agents whose behavior is left implicit. In our model, the DHCP server represents another type of application program. domain DHCP(SERVER We can now define AGENT as a derived domain, where we assume the three underlying domains COMMUNICATOR, CONTROL(POINT, DEVICE and DHCP(SERVER to be pairwise disjoint. AGENT ( APPLICATION ( COMMUNICATOR APPLICATION ( CONTROL(POINT ( DEVICE ( DHCP(SERVER An overview of the various agent types and the relations between them is presented in the form of an UML class diagram in Figure 3. In the subsequent sections, the keyword me will be used to identify the agent under consideration, i.e. as identified by a given context. In ASMs, classes are dynamic universes of objects. Consequently, a field f of type D of a class C can be viewed as a dynamic unary function from C to D, in symbols f : C ( D. For instance, a communicator has a field routingTable denoting a mapping from addresses to sets of communicators. routingTable: COMMUNICATOR ( Map of ADDRESS to (Set of COMMUNICATOR)  Figure 3: UML class diagram of the agents. Discrete Time and Timeout Events Time values are represented as real numbers by the elements of a linearly ordered domain TIME. We can assume that TIME ( REAL and define the relation ( on time values through the corresponding relation on real numbers. A domain DURATION represents finite time intervals as differences between time values. domain TIME, domain DURATION Our notion of time is based on the view that we can only observe, but not control, how physical time evolves. Accordingly, we introduce a monitored, nullary function now taking values in TIME. Intuitively, now represents the global system time as measured by some discrete clock. One can reasonably assume that the values of now change monotonically over ASM runs. monitored now : TIME initially startTime An agent a may employ several distinct timers for different purposes, where each individual timer t has its own default duration effectively determining the expiration time when setting t. In a given state, a timer t is active if and only if its expiration time time(t) is greater than the value of now. Otherwise, t is called expired. domain TIMER(TYPE ( {dhcpClient, discovery, (} duration : AGENT ( Map of TIMER(TYPE to DURATION time : AGENT ( Map of TIMER(TYPE to TIME For a given timer t of agent a, the operation of setting t can thus be defined as follows. SetTimer(a,t) ( time(a)(t):= now + duration(a)(t) In a given state, a predicate Timeout indicates for given timer instance t and agent a whether the timer instance is active or has expired. Timeout : AGENT ( Map of TIMER(TYPE to BOOL, Timeout(a,t) = now ( time(a)(t) Addresses and Messages This section defines the representation of addresses and messages together with the mechanisms for sending and receiving messages. Our model abstractly reflects the view of the transport layer protocols TCP and UDP. At the given abstraction level, the only real difference between TCP and UDP is that the former is reliable whereas the latter provides a best-effort, connectionless packet delivery service, i.e. messages may get lost. Addresses We introduce a static universe ADDRESS of IP addresses that are extended by protocol port numbers to refer to the global TCP/UDP address space. For each application under consideration, a dynamic function address identifies an element from ADDRESS. A distinguished address called thisDevice is used as a source address for newly added devices that do not yet have an otherwise defined IP address. static domain ADDRESS address : APPLICATION ( ADDRESS When a new device is added to the network, it does not yet have an IP address, but uses its hardware address instead for communication with a DHCP server [ REF _Ref511556901 \r \h  \* MERGEFORMAT 8]. We abstractly represent hardware addresses as elements of a static domain HW(ADDRESS. static domain HW(ADDRESS hwAddress : DEVICE ( HW(ADDRESS Representation of Messages Messages are uniformly represented as elements of a dynamic domain MESSAGE. Each message is of a certain type from the static domain MSG(TYPE. The message type determines whether a message is transmitted using UDP or TCP, though we do not make this distinction explicit. domain MESSAGE initially empty domain MSG(TYPE ( {advertisement, search, request, response, revocation, dhcpOffer, dhcpDiscover} A message uniquely identifies a sender, a receiver, a message type, and the actual message content. The content can be any finite representation of information to be transferred from a sender to a receiver. sndr : MESSAGE ( ADDRESS rcvr : MESSAGE ( ADDRESS type : MESSAGE ( MSG(TYPE data : MESSAGE ( DATA Sending and Receiving Messages An application is running on some host connected to one or more local networks. The operation of sending a message as well as the delivery of a message both require some form of direct interaction between this host and one of its local networks. We can assume here that the network is uniquely determined by the application. Abstractly, this relation is expressed using a unary dynamic function network defined on applications. network : APPLICATION ( COMMUNICATOR Local Mailboxes. An agent has a local mailbox for storing messages until these messages will be processed. According to this view, the mailbox of a network agent represents the set of messages that are currently in transit on the related network. The mailbox of an application represents its local input port as identified by the respective port number for this application. mailbox : AGENT ( Set of MESSAGE initially empty Message Output. We introduce the output operation defined below for applications to send a message over a local network. Here me refers to the application sending the message. The extend operation below creates a new message object. The effect of the send operation is that the message is put into the mailbox of the network agent. Output(r:ADDRESS,d:DATA,t:MSG(TYPE)= extend MESSAGE with m sndr(m):(address(me) rcvr(m):(r data(m):(d type(m):(t mailbox(network(me)) := mailbox(network(me)) ( {m} Multicasting and Broadcasting. Depending on the applied mechanism for message delivery, one typically classifies addressing as unicasting, multicasting or broadcasting. Conceptually multicasting can be viewed as a generalization of all other address forms [ REF _Ref509221210 \r \h  \* MERGEFORMAT 7]. According to this view, we associate with every address some collection of applications, called a multicast group. More specifically, the group associated with a unicast address consists of a single application. The group associated with a broadcast address consists of all applications on a given local network. Notice that multicast groups change dynamically as applications come and go. Our model distinguished two basically different multicast groups: control points and devices. Abstract Protocol Model In this section we define a high-level ASM model of the UPnP protocol. This ASM model is then refined into an executable AsmL model by adding details related to the object-oriented specification style of AsmL as will be described in Section  REF _Ref516565819 \r \h 4. Initial States An initial state reflects the particular system configuration under consideration. As such it identifies some finite collection of a priori given agents, one for each control point, each device and each communicator. Depending on the type of an agent, it executes the program RunControPoint, RunDevice, or RunNetwork. The behavior of DHCP server agents is not explicitly defined in terms of a program; rather it is determined by the respective actions controlled by the external world. domain PROGRAM ( {RunControlPoint, RunDevice, RunNetwork} Integrity Constraint. In every state of an ASM run, including the initial state, the following property holds. ( x ( AGENT: program(x) = RunControlPoint, if x ( CONTROLPOINT RunDevice, if x ( DEVICE RunNetwork, if x ( COMMUNICATOR Remark. In the model of the UPnP protocol, we abstract from any device specific properties but concentrate on those aspects of behavior that are common to all UPnP devices according to [ REF _Ref509291474 \r \h  \* MERGEFORMAT 1]. The resulting device model thus provides a basic description that may be extended by adding the device specifics depending on the particular type of device. Technically this is achieved through a parallel composition of the two device models, the basic one and the specific one. Network Model We assume a TCP/IP network using TCP and UDP as transport protocols for the transfer of messages between applications running on different machines. Recall that UDP uses the same unreliable datagram delivery semantics as IP [ REF _Ref509221210 \r \h  \* MERGEFORMAT 7]. As such it provides a connectionless, best-effort message delivery service, where messages may be lost, duplicated, delayed or delivered out of order without receiving any notification. Hence, it is in the responsibility of an application to tolerate this behavior. Delivery and Routing. Collectively, the communicators solve the task of globally transferring messages between applications running on hosts connected to the network. Communicators thus imitate the behavior of IP routers, where we encode the topological information in a dynamic mapping called routingTable. Intuitively a routingTable of a given communicator maps a non-local addresses to the correct neighboring communicators. Notice that a multicast address may refer to several network communicators. routingTable : COMMUNICATOR ( Map of ADDRESS to COMMUNICATOR Furthermore, communicators handle the delivery of messages to destinations on a given local network. That is, given the destination address of a message in conjunction with a local network, a (possibly empty) set of related destinations on this network must be identified. We therefore introduce a dynamic mapping of addresses called addressTable. Intuitively, addressTable is a mapping from addresses of multicast groups to addresses of related group members. addressTable : COMMUNICATOR ( Map of ADDRESS to Set of ADDRESS Time to Live (TTL). To limit the maximum number of routers that a message can pass on its way from the sender host to a destination host, a time-to-live or TTL, is assigned when the message is created. Each router decrements the TTL by one until the message eventually reaches its final destination or will be discarded. UPnP defines the initial TTL to be 4. ttl : MESSAGE ( {0,1,2,3,4} initially 4 Message Transfer. The transfer of messages may be delayed in an unpredictable manner depending on resource limitations of the underlying physical network. Since we abstract here from lower level network layers, the decision whether a messages is ready to be delivered in a given state of the network is stated through an externally controlled predicate ReadyToDeliver. (Notice that for some UDP message m the condition ReadyToDeliver(m) may never hold, implying that the message effectively gets lost.) monitored ReadyToDeliver : MESSAGE ( BOOL initially false Now, we can formalize the network behavior in terms of interacting communicators executing the below program. This program performs three basically different steps, namely: (1) limited broadcasting within the local network; (2) delivery of multicast messages on a local network; (3) routing of messages through a global network. To identify local networks, a unique network identifier, called netid, is associated with each communicator. The network identifier can be derived from an address by inspecting the network mask part of the address. In the program below me refers to a communicator. RunCommunicator ( choose msg ( mailbox(me): ReadyToDeliver(msg) do mailbox(me):= mailbox(me) - {msg} if rcvr(msg) = broadcast then forall a ( APPLICATION: network(a) = me do DeliverMessageToMailbox(msg,address(a),a) else forall adr ( addressTable(me)(rcvr(msg)) do if netid(adr)= netid(me) then choose a ( APPLICATION: address(a) = adr do DeliverMessageToMailbox(msg,adr,a) else if ttl(msg) > 0 then let c = routingTable(me)(adr) in DeliverMessageToMailbox(msg,adr,c) The operation of delivering a message to the mailbox of a given agent is defined below. Applications and communicators are treated uniformly. They are both agents that have a mailbox and the operation performed on this mailbox (i.e., inserting a copy of some message) does not depend on the particular type of agent. DeliverMessageToMailbox(msg:MESSAGE,adr:ADDRESS,ag:AGENT) = extend MESSAGE with m sndr(m):( sndr(msg), rcvr(m):( adr, type(m):( type(msg), data(m):( data(msg), ttl(m) := ttl(m)-1 mailbox(ag):= mailbox(ag) ( {m} Device Model In this section we define the device model as parallel composition of a number of synchronously operating ASM models, each of which runs a different protocol step. For the purpose of illustrating the device program, we focus here on Addressing, Discovery and Control. Device Status. In a given system state, a UPnP device may or may not be connected to a network. Regarding the connection status of a device, there are basically three different situations: inactive: the device is currently not connected to a network; alive: the device is connected and will probably remain connected for some time; byebye: the device is connected but is about to be removed from the network. The status of a device is affected by actions and events in the external world. Therefore, it may change in a basically unpredictable way, but one can assume that devices initially are not connected. To model the device status, we introduce an externally controlled dynamic function status defined on devices. monitored status : DEVICE ( { inactive, alive, byebye } In the device program defined below, me refers to a device agent. RunDevice = if status(me) ( inactive then RunAddressing RunDiscovery RunDescription RunControl RunEventing RunPresentation Addressing. IP address management requires a DHCP server to uniquely assign an IP address whenever a new host (for which no IP address is specified manually) is added to a network [ REF _Ref511556901 \r \h  \* MERGEFORMAT 8]. A key idea behind DHCP is to enable communication between a DHCP server and the host's DHCP client using the hardware address of the host. That is, as reply to a DHCPDISCOVER message from a client, the server broadcasts a DHCPOFFER message identifying the IP address as well as the hardware address of the host. By checking the hardware address, the host identifies itself as receiver (and can thus install the IP address). Alternatively, a host may obtain a temporary IP address through auto IP addressing in case that a DHCP server is not available (or reachable). This temporary address may then be used until a matching DHCPOFFER message is received. To distinguish various situations with regard to a device's address status, we use the following abbreviations for checking whether a message is an offer from a matching DHCP server offer. DhcpOffer(m) ( (type(m) = dhcpoffer and hwAddressEncodedIn(data(m)) = hwAddress(me)) We abstract here from the device specific algorithm used for auto IP addressing by making a non-deterministic choice. To check the result, we assume to have some externally controlled decision procedure as represented by the monitored predicate ValidAutoIPAdr. Without specifying any further details, we expect the resulting auto IP addresses to fulfill the given constraints. monitored ValidAutoIPAdr : DEVICE ( ADDRESS ( BOOL RunAddressing ( if address(me) = thisDevice or AutoConfiguredAddress(me) then RunDHCPclient if address(me) = thisDevice and (DhcpOfferReceived then choose address ( ADDRESS: ValidAutoIPAdr(me,address) do address(me):= address AutoConfiguredAddress(me):= true where DhcpOfferReceived ( ( m ( mailbox(me): DhcpOffer(m) Even in case that a DHCPOFFER has been received, a host may continue to use a temporary IP address for some time until it eventually switches to the server assigned IP address. In [ REF _Ref509291474 \r \h  \* MERGEFORMAT 1], the condition that affects the switching of addresses is left abstract. Accordingly, we model this behavior by introducing an externally controlled predicate SwitchAddressEvent defined on devices. monitored SwitchAddressEvent : DEVICE ( BOOL initially false When a DHCP client becomes activated, it generates an initial DHCPDISCOVER message immediately. To distinguish this situation from those where a timeout event triggers the generation of subsequent DHCPDISCOVER messages, we introduce a special flag. IssueInitialDiscover : DEVICE ( BOOL initially true RunDHCPclient = choose m ( mailbox(me): DhcpOffer(m) do if SwitchAddressEvent (me) then address(me):= rcvr(m) AutoConfiguredIPAdr(me):= false AdvertiseNewAds(rcvr(m)) RevokeOldAds(address(me)) if (DhcpOfferReceived then if Timeout(me,dhcpClientTimer) or IssueInitialDiscover(me) then Output(255.255.255.255,dhcpdiscover,hwAddress(me)) SetTimer(me,dhcpClientTimer) IssueInitialDiscover(me):= false where DhcpOfferReceived ( exists m ( mailbox(me): DhcpOffer(m) After switching to a new address, the device must update and reissue its advertisements as well as revoke the old advertisements. These operations are further specified in the AsmL model. Discovery. The discovery part of the UPnP protocol is based on UDP. Since messages may get lost, devices inform control points about their presence and the services they offer reissuing their advertisements on a regular basis. Additionally, a device replies to service requests from control points in case that a request matches with a service offered by the device, as indicated by the following predicate. MatchingServiceRequest : SERVICE * MESSAGE ( BOOL RunDiscovery ( NotifyAdsStatus RespondToSearch NotifyAdsStatus ( if address(me) ( thisDevice and Timeout(me,discoveryTimer) then SetTimer(me,discoveryTimer) if status(me) = alive then NotifyDeviceAvailable(controlPoints) if status(me) = byebye then NotifyDeviceUnavailable(controlPoints) status(me):= inactive We identify the services associated with a root device or one of its embedded devices using a static function srvcs defined on devices. srvcs : DEVICE ( Set of SERVICE RespondToSearch ( choose m ( mailbox(me) : type(m) = search do mailbox(me)(m) := false if exists s ( srvcs(me): MatchingServiceRequest(s,m) then NotifyDeviceAvailable(sndr(m)) The control part of a device is responsible for invoking the pending requests and generating the responses to those requests. The requests are handled one at a time. Each request message is assumed to have a data part that is a map identifying a service (Service), an action (Action) and arguments (Arguments) for that action. A response message is sent back to the sender of the request message. The data of the response message records the result of the action call. See the AsmL model for further details. RunControl ( if not address(me)=thisDevice then choose m ( mailbox(me) : type(m) = request and data(m)(Service) ( srvcs(me) do let res = Invoke(data(m)(Service),data(m)(Action),data(m)(Arguments)) mailbox(me)(m) := false Output(address(me), sndr(m), {Result mapsto res}, response) Executable Protocol Model and GUI The protocol model defined in the previous section can be refined into an executable AsmL program. The AsmL model is written in an object-oriented style. This is for example reflected by the fact that the identity of agents is mostly not explicitly mentioned but is implicitly given by the identity of the object (me). The object model was illustrated above with a UML class diagram. The intension is that the AsmL model is self-explanatory. Many of the comments regarding the logical structure of the model were already given above and are not repeated here. The rest of the section is structured as follows. We start by mentioning the GUI. The top level loop that drives the model, as well as the methods defining the interaction between the model and the environment, are part of the interface definition to the GUI. Next we define the universes of the different kind of entities that we need. We then describe the communication model and the message structure needed to support it. Finally we define the AsmL models for communicators, control points and devices, respectively. The last three subsections constitute the main part of the overall AsmL model. Gaphical User Interface It is important to have a GUI that allows you to visualize the state in a way that is close to the intuitive understanding, and that allows you to interact with the AsmL model. The following figure shows a snapshot of the simulator in a setup with two separate network communicators, one for devices and one for control points. There is a DHCP server whose behavior is completely controlled by the external world through the GUI. There is one control point and one device. The control point is receiving advertisements and revocations (of old advertisements) from the device (some of the advertisements are still in transfer), as a result of the device having received a new IP address from the DHCP server.  Figure 5: Snapshot of the UPnP Simulation tool. In order to interact with the model using a GUI (as a client) we encapsulate the model in a COM component (acting as a server) that exposes the methods needed to interact with the model through an interface. The COM server is named UPnPModelServer. import COM serverName = "UPnPModelServer" We declare an interface called IServer (extension with the builtin interface IDispatch is needed for automation support). interface IServer extends IDispatch The first method that the user of this server must do is to invoke the Initialize method. All IServer methods are declared and implemented in Appendix II. Executable Protocol Model var CONTROLPOINTs as Set[CONTROLPOINT] = {} var DEVICEs as Set[DEVICE] = {} var DHCPSERVERs as Set[DHCPSERVER] = {} APPLICATIONs() as Set[APPLICATION] = {c as APPLICATION | c in CONTROLPOINTs} union {d as APPLICATION | d in DEVICEs} union {s as APPLICATION | s in DHCPSERVERs} var COMMUNICATORs as Set[COMMUNICATOR] = {} var now as Integer = 0 In order to run the programs of all the agents in AsmL, we introduce the following top-level rule. The executions of several agents are generally simulated by interleaving. Here we may in fact run them all simultaneously because they do not share variables, all communication between agents takes place via message passing. RunUPnP() = forall c in CONTROLPOINTs do c.RunControlPoint() forall d in DEVICEs do d.RunDevice() forall n in COMMUNICATORs do n.RunNetwork() Timers enum TIMERTYPE dhcpClientTimer discoveryTimer Timeout(d as DEVICE, t as TIMERTYPE) as Boolean = now >= d.time(t) SetTimer(d as DEVICE, t as TIMERTYPE) = d.time(t):= now + d.duration(t) Communication Model In AsmL the host's object id is used as its hardware address. hwAdr(h as APPLICATION) as String = asString(h) IP Address Space structure ADDRESS mask as String adr as String port as Integer asString() as String = adr thisDevice = ADDRESS("","0.0.0.0",0) UnspecifiedIPAdr(a as ADDRESS) as Boolean = (a = thisDevice) Multicast and Broadcast Addresses We distinguish two different multicast groups: devices and control points. Each multicast group is uniquely identified by a distinguished IP address. controlPoints = ADDRESS(controlPointNetId,"2.2.2.255",0) devices = ADDRESS(deviceNetId,"1.1.1.255",0) The distinguished IP address 255.255.255.255 is used for broadcast. broadcast = ADDRESS("","255.255.255.255",0) Representation of Messages var MESSAGEs as Set[MESSAGE] = {} enum MSGTYPE advertisement search request response revocation dhcpoffer dhcpdiscover Depending on the type of the message the data may include different fields of information each encoded as a string. The content is therefore a map from field identifiers to their respective values. The number of fields is determined by the type of the message. enum FIELD Device Service Action Arguments Lifetime HardwareAddress NewAddress SearchPattern Result structure DATA f as FIELD -> String service() as String = f(Service) action() as String = f(Action) args() as String = f(Arguments) duration() as Integer = Integer.fromString(f(Lifetime)) hwAdr() as String = f(HardwareAddress) newAdr() as ADDRESS = ADDRESS(deviceNetId,f(NewAddress),0) search() as String = f(SearchPattern) emptycontent as DATA = DATA({|->}) class MESSAGE sndr as ADDRESS rcvr as ADDRESS data as DATA tYPE as MSGTYPE var time as Integer Sending and Receiving Messages The underlying communication protocol is based on an asynchronous communication model. For simplicity, we assume unbounded communication bandwidth. Control points as well as devices may send and receive any finite number of messages at a time. Agents Each agent has a private mailbox into which messages can be inserted by other agents. class AGENT() var mailbox as Set[MESSAGE] = {} Applications An application is an agent with a unique IP address and belongs to a certain network. It outputs its messages to the local network it belongs to. class APPLICATION(a as ADDRESS, n as COMMUNICATOR) extends AGENT() var adr as ADDRESS = a var network as COMMUNICATOR = n Output(s as ADDRESS, r as ADDRESS, c as DATA, t as MSGTYPE) = let m = new MESSAGE(s, r, c, t, now) MESSAGEs(m) := true network.mailbox(m) := true Network Model Each communicator has a netid, an address table and a routing table. class COMMUNICATOR(t as String, atbl as ADDRESS -> Set[ADDRESS], rtbl as ADDRESS -> COMMUNICATOR) extends AGENT() netid as String = t addressTable as ADDRESS -> Set[ADDRESS] = atbl var routingTable as ADDRESS -> COMMUNICATOR = rtbl RunNetwork class COMMUNICATOR... RunNetwork() = choose msg in mailbox do mailbox(msg) := false if msg.rcvr = broadcast then // limited broadcast to all local applications forall a in APPLICATIONs() where a.network = me do DeliverMessageToMailbox(msg,broadcast,a) else if addressTable(msg.rcvr) <> undef then forall adr in addressTable(msg.rcvr) do //if the address is local if adr.mask = netid then choose a in APPLICATIONs() where a.adr = adr do DeliverMessageToMailbox(msg,adr,a) else //obs! ttl is not implemented if routingTable(adr) <> undef then DeliverMessageToMailbox(msg,adr,routingTable(adr)) DeliverMessageToMailbox(m as MESSAGE, adr as ADDRESS, ag as AGENT) = let msg = new MESSAGE(m.sndr, m.rcvr, m.data, m.tYPE, m.time) MESSAGEs(msg) := true ag.mailbox(msg) := true DHCP Server The behavior of dhcp servers is unspecified. class DHCPSERVER(adr' as ADDRESS, network' as COMMUNICATOR) extends APPLICATION(adr', network') Control Point Model Control points may invoke actions. Each action request refers to a particular target device via its address (dadr), and contains an action call with a given name (actn) and arguments (args) targeted to a specific service (srvc) within that device. structure ACTIONREQUEST dadr as ADDRESS srvc as String actn as String args as String NoAction = ACTIONREQUEST(thisDevice,"","","") A control point is a host that has a fixed type and UID. class CONTROLPOINT(adr' as ADDRESS, network' as COMMUNICATOR, type' as String, uid' as String) extends APPLICATION(adr',network') tYPE as String = type' uid as String = uid' In a given state, we associate with each control point a (possibly empty) set of advertisements. Conceptually, advertisements are messages of type advertisement. class CONTROLPOINT... var ads as Set[MESSAGE] = {} Run the control point. class CONTROLPOINT... RunControlPoint() = SearchForDevices() ControlDevices() UpdateAds() EmptyMailbox() EmptyMailbox() = forall m in mailbox do mailbox(m) := false Search for Devices When a control point is added to the network, the UPnP discovery protocol allows that control point to search for devices of interest on the network. To specify the devices of interest for a given control point, a monitored function searchPattern yields a corresponding search pattern. The search pattern may either be a UID or a type of a device. We assume here that a search for devices may be invoked at any time. class CONTROLPOINT... var searchPattern as String = "" SearchForDevices() = if searchPattern <> "" then Output(adr,devices,DATA({SearchPattern |-> searchPattern}), search) searchPattern := "" Processing Ads class CONTROLPOINT... UpdateAds() = IncludeNewAds() RemoveExpiredAds() RemoveRevokedAds() IncludeNewAds() = forall m in mailbox where m.tYPE = advertisement do m.time := now + m.data.duration() // set expiration time ads(m) := true // save the ad RemoveExpiredAds() = forall ad in ads where ad.time <= now do ads(ad):= false RemoveRevokedAds() = forall m in mailbox where m.tYPE = revocation do forall ad in ads where ad.data = m.data and ad.sndr = m.sndr do ads(ad) := false Controlling Devices Each control point has a monitored function action that may contain a request to be issued by the control point. class CONTROLPOINT... var action as ACTIONREQUEST = NoAction ControlDevices() = InvokeAction() ProcessResponse() InvokeAction() = if action <> NoAction then Output(adr,action.dadr,DATA({Service |-> action.srvc, Action |-> action.actn, Arguments |-> action.args}), request) action := NoAction ProcessResponse() = forall m in mailbox where m.tYPE = response do PrintResponse(me, m) // external function Device Model The AsmL model for UPnP devices formalizes device behavior through the program of device agents. In a given machine state, each device agent executes the rule RunUPnPDevice defined below. The status of a device is either alive, byebye or inactive. It is given by the shared function status. enum DEVICESTATUS alive byebye inactive class DEVICE(adr' as ADDRESS, network' as COMMUNICATOR, type' as String, uid' as String, srvcs' as Set[SERVICE], ads' as Set[DATA], duration' as TIMERTYPE -> Integer, time' as TIMERTYPE -> Integer) extends APPLICATION(adr',network') tYPE as String = type' uid as String = uid' var srvcs as Set[SERVICE] = srvcs' ads as Set[DATA] = ads' duration as TIMERTYPE -> Integer = duration' var time as TIMERTYPE -> Integer = time' var status as DEVICESTATUS = alive RunDevice() = if status <> inactive then RunAddressing() RunDiscovery() RunDescription() RunControl() RunPresentation() RunEventing() Addressing class DEVICE... var AutoConfiguredIPAdr as Boolean = false var ContinueAutoIP as Boolean = false SupportsAutoIPAdr as Boolean = true RunAddressing() = if UnspecifiedIPAdr(adr) or AutoConfiguredIPAdr then RunDHCPclient() //DHCP if UnspecifiedIPAdr(adr) and not DhcpOfferReceived() then if AutoIPEnabled() then RunAutoIPAddressing() //AutoIP AutoIPEnabled() as Boolean = SupportsAutoIPAdr and (Timeout(me,dhcpClientTimer) or ContinueAutoIP) DhcpOfferReceived() as Boolean = exists m in mailbox where m.tYPE = dhcpoffer and m.data.hwAdr() = hwAdr(me) class DEVICE... var candidateAdr as ADDRESS = thisDevice Dynamic Host Configuration Protocol class DEVICE... var SwitchIPAdrEvent as Boolean = true var IssueInitialDiscover as Boolean = true RunDHCPclient() = if DhcpOfferReceived() then if SwitchIPAdrEvent then choose m in mailbox where m.tYPE = dhcpoffer and m.data.hwAdr() = hwAdr(me) do let newAdr = m.data.newAdr() mailbox(m) := false MESSAGEs(m) := false adr := newAdr AutoConfiguredIPAdr := false AdvertiseNewAds(newAdr) RevokeOldAds(adr) elseif Timeout(me,dhcpClientTimer) or IssueInitialDiscover then //provide the hardware address of the device in the message data Output(adr, broadcast,DATA({HardwareAddress |-> hwAdr(me)}),dhcpdiscover) SetTimer(me,dhcpClientTimer) IssueInitialDiscover := false RevokeOldAds(a as ADDRESS) = if not UnspecifiedIPAdr(adr) then forall ad in ads do Output(a, controlPoints, ad, revocation) AdvertiseNewAds(a as ADDRESS) = forall ad in ads do Output(a, controlPoints, ad, advertisement) Auto-IP Addressing class DEVICE... var CandidateAdrIsValid as Boolean = false var mode as AUTOIPMODE = chooseIPAdr RunAutoIPAddressing() = match mode with chooseIPAdr : ChooseIPAdr() ContinueAutoIP := true probe : Probe() checkIPAdr : CheckIPAdr() ChooseIPAdr() = candidateAdr := guessAutoIPAdr(me) mode := probe Probe() = CandidateAdrIsValid := not(exists h in APPLICATIONs() where h.adr = candidateAdr) mode := checkIPAdr CheckIPAdr() = if CandidateAdrIsValid then adr := candidateAdr AutoConfiguredIPAdr := true ContinueAutoIP := false else mode := chooseIPAdr Discovery class DEVICE... RunDiscovery() = if not UnspecifiedIPAdr(adr) then RespondToSearch() if Timeout(me, discoveryTimer) then match status with alive: SetTimer(me, discoveryTimer) NotifyDeviceAvailable(controlPoints) byebye: NotifyDeviceUnavailable() status := inactive NotifyDeviceAvailable(rcvr as ADDRESS) = forall a in ads do Output(adr, rcvr, a, advertisement) NotifyDeviceUnavailable() = forall a in ads do Output(adr, controlPoints, a, revocation) RespondToSearch() = if (exists m in mailbox where m.tYPE = search) then choose m in mailbox where m.tYPE = search do mailbox(m) := false MESSAGEs(m) := false if SearchMatches(m) and status=alive then NotifyDeviceAvailable(m.sndr) SearchMatches(m as MESSAGE) as Boolean = (m.data.search() = tYPE or m.data.search() = uid) Description class DEVICE... RunDescription() = skip Presentation class DEVICE... RunPresentation() = skip Eventing class DEVICE... RunEventing() = skip Control class DEVICE... RunControl() = if not UnspecifiedIPAdr(adr) then choose m in mailbox where m.tYPE=request and (exists s in srvcs where m.data.service()=s.GetId()) do let s = unique s in srvcs where m.data.service()=s.GetId() let res = s.Invoke(ACTIONCALL(m.data.action(), m.data.args())) mailbox(m) := false Output(adr, m.sndr, DATA({Result |-> res.asString()}), response) //clean up the mailbox forall m in mailbox where UnwantedMessage(m) do mailbox(m) := false UnwantedMessage(m as MESSAGE) as Boolean = m.tYPE = dhcpdiscover or (m.tYPE = dhcpoffer and not AutoConfiguredIPAdr and not UnspecifiedIPAdr(adr)) enum AUTOIPMODE chooseIPAdr probe checkIPAdr SERVICE Interface Each service implements the SERVICE interface that allows the device to get the id of this service and to invoke an action on this service. structure ACTIONCALL name as String //name of the action args as String //arguments .. enum RESULTSTATUS ok err structure RESULT stat as RESULTSTATUS //normal result or an error tag res as String //the result value interface SERVICE GetId() as String Invoke(actn as ACTIONCALL) as RESULT Conclusions We construct a high-level Abstract State Machine model for Universal Plug and Play. The model is based on the ASM paradigm for distributed systems with real-time constraints and is executable in principle. For practical execution, we use AsmL, the Abstract state machine Language, developed at Microsoft Research and integrated with Visual Studio and COM. This gives us an AsmL model, a refined version of the ASM model. The third part of this project is a GUI by means of which the runs of the AsmL model are controlled and inspected at various levels of detail as required for e.g. simulation and conformance testing. While the ASM approach is very general, the domain of communication software is important enough to command a particular attention. There is a stream of ASM work specific to this domain; a good example is the SDL paper [ REF _Ref516049189 \r \h 14]. The current paper is another example. The common method in the stream is to turn, systematically and gradually, the given informal descriptions of complex distributed systems, like the UPnP standard [ REF _Ref509291474 \r \h 1], into high-level executable models. Our ASM model of the UPnP protocol is on the level of abstraction of the informal description. The basic objects of the protocol are present in the model, and players of the protocol become agents of the model. Moreover, the ASM model is component-based so that it splits into three separate submodels (for control points, devices and the communication network respectively) with clearly identified interfaces. Even though the current version of our UPnP model does not cover all protocol steps, the resulting formalization captures all the significant aspects of UPnP: concurrency, communication and timing. The abstract operational view of ASMs thereby allows a seamless integration of control and data-oriented aspects of behavior specifications. Moreover, we combine synchronous and asynchronous execution paradigms, associated with the application programs and the communication network respectively, in one common model. In that sense, there are no conceptual difficulties to include the missing details (protocol steps) as they all rely on the same architectural model. This becomes obvious by inspecting and running the executable model in [15]. Acknowledgements We thank Jeffrey Schlimmer from the UPnP group at Microsoft for inspiring discussions and helpful background information about the development and standardization of UPnP. We thank Colin Campbell for inspiring discussions and cooperation on modeling of the individual UPnP devices. References UPnP Device Architecture V1.0. Microsoft Universal Plug and Play Summit, Seattle 2000, Microsoft Corporation, Jan. 2000. Universal Plug and Play Forum. Official web site of the UPnP Forum. URL: www.upnp.org. W. Grieskamp, Y. Gurevich, W. Schulte and M. Veanes. Testing with Abstract State Machines. In Proc. ASM'2001. Y. Gurevich. Evolving Algebras 1993: Lipari Guide, Specification and Validation Methods, ed. E. Brger, Oxford University Press, 1995, 9-36. Y. Gurevich. Sequential Abstract State Machines Capture Sequential Algorithms", ACM Transactions on Computational Logic, vol. 1, no. 1, July 2000, 77-111. W. Schulte et al. AsmL Version 1.5, Internal Report, Microsoft Research, Foundations of Software Engineering, Redmond, WA, April 2001. D. E. Comer. Internetworking with TCP/IP, Principles, Protocols, and Architectures. Prentice Hall, 2000. R. Droms and T. Lemon. The DHCP Handbook, Understanding, Developing, and Managing Automated Configuration Services. Macmillan Technical Publishing, 1999. Microsoft Research, Foundations of Software Engineering, Redmond, USA, http://research.microsoft.com/foundations. Abstract State Machines, http://www.eecs.umich.edu/gasm/. ITU-T Recommendation Z.100: Languages for Telecommunications Applications - Specification and Description Language (SDL), Annex F: SDL Formal Semantics Definition, International Telecommunication Union, Geneva, 2000. Y. Gurevich, W. Schulte and M. Veanes, Toward Industrial Strength Abstract State Machines, in Proc. ASM'2001, 2001. Don Box, Essential COM, Addison-Wesley, Reading, MA, 1998. R. Eschbach, U. Glsser, R. Gotzhein and A. Prinz. On the formal semantics of SDL-2000: a compilation approach based on an Abstract SDL Machine. In Abstract State Machines - Theory and Applications. Y. Gurevich, P.W. Kutter, M. Odersky and L. Thiele (Eds.), Lecture Notes in Computer Science, Vol. 1912, Springer-Verlag, 2000. Y. Gurevich. The ASM Paradigm, in Proc. ASM'2001, 2001. Appendix I: AsmL model of CD Player The following is a sample CD Player device specification. createCDPLAYER(netw as COMMUNICATOR) as DEVICE = let uid = "Device" + asString(size(DEVICEs)+1) //create a new UID let changer = new CHANGEDISC() let player = new PLAYCD() let ads = { DATA({Lifetime |-> "50", Device |-> "CDPlayer"}), DATA({Lifetime |-> "50", Service |-> "CDPlayer::ChangeDisc"}), DATA({Lifetime |-> "50", Service |-> "CDPlayer::PlayCD"}) } let dmap = { dhcpClientTimer |-> 30, discoveryTimer |-> 50 } let tmap = { dhcpClientTimer |-> now + 30, discoveryTimer |-> now } let dev = new CDPLAYER(netw, uid, changer, player, ads, dmap, tmap) changer.device := dev player.device := dev return(dev as DEVICE) class CDPLAYER(netw' as COMMUNICATOR, duid' as String, changer' as CHANGEDISC, player' as PLAYCD, discoveryads as Set[DATA], dmap' as TIMERTYPE -> Integer, tmap' as TIMERTYPE -> Integer) extends DEVICE(thisDevice, netw', "CD Player", duid', {changer' as SERVICE, player' as SERVICE}, discoveryads, dmap', tmap') changer as CHANGEDISC = changer' player as PLAYCD = player' Extended SERVICE interface interface ExtSERVICE extends SERVICE Get UPnP related data. interface ExtSERVICE... GetType() as String GetUID() as String Get signature information (variable, constant, sensor names, action names). interface ExtSERVICE... GetStateVars() as String GetStateConstants() as String GetStateSensors() as String GetActions() as Set[String] Get values of state functions. interface ExtSERVICE... GetStateVarValue(v as String) as String GetStateConstantValue(v as String) as String Probe the sensors. interface ExtSERVICE... IsStateSensorEnabled(v as String) as Integer GetStateSensorValue(v as String) as String SetSensorValue(sensor as String, val as String) Get the value of the monitored function holding the pending action call. interface ExtSERVICE... GetPendingActionCall() as String Get high-level description of the state formulated in natural language. interface ExtSERVICE... GetStateDescription() as String Get the value of the last result. interface ExtSERVICE... GetActionResult() as String CHANGEDISC Service class CHANGEDISC implements ExtSERVICE var device as CDPLAYER = undef State UPnP state variables class CHANGEDISC... var OccupiedSlots as Set[Integer] = {} var CurrentSlot as Integer = 0 var DoorIsOpen as Boolean = false Sensors class CHANGEDISC... var DoorIsStuck as Boolean = false Constants class CHANGEDISC... allSlots as Set[Integer] = {0..4} Action call and result class CHANGEDISC... var action as ACTIONCALL = ACTIONCALL("","") var res as RESULT = RESULT(ok,"") ExtSERVICE methods UPnP data class CHANGEDISC... GetType() as String = "ChangeDisc" GetUID() as String = (device.uid + "::ChangeDisc") Signature class CHANGEDISC... GetStateVars() as String = "{OccupiedSlots,CurrentSlot,DoorIsOpen}" GetStateConstants() as String = "{allSlots}" GetStateSensors() as String = "{DoorIsStuck,trayHasDisc}" GetActions() as Set[String] = ({"AddDisc","NextDisc","PrevDisc","RandomDisc", "OpenDoor","CloseDoor","ToggleDoor", "HasTrayDisc","IsDoorOpen"}) Values class CHANGEDISC... GetStateVarValue(v as String) as String = match v with "OccupiedSlots" : OccupiedSlots.asString() "CurrentSlot" : CurrentSlot.asString() "DoorIsOpen" : DoorIsOpen.asString() GetStateConstantValue(v as String) as String = match v with "allSlots" : allSlots.asString() Probe sensors class CHANGEDISC... GetStateSensorValue(v as String) as String = match v with "DoorIsStuck" : DoorIsStuck.asString() "trayHasDisc" : trayHasDisc().asString() IsStateSensorEnabled(v as String) as Integer = match v with "DoorIsStuck" : 1 "trayHasDisc" : if DoorIsOpen then 1 else 0 SetSensorValue(v as String, val as String) = match v with "DoorIsStuck" : DoorIsStuck := (val = "true") "trayHasDisc" : if DoorIsOpen then OccupiedSlots(CurrentSlot) := (val = "true") GetPendingActionCall class CHANGEDISC... GetPendingActionCall() as String = if action.name = "" then "" else action.name + "(" + action.args + ")" GetStateDescription class CHANGEDISC... GetStateDescription() as String = let s1 = if DoorIsOpen then "1. Door is open.\n" else "1. Door is closed\n" let s2 = if trayHasDisc() then "2. There is a CD on the tray.\n" else "2. There is no CD on the tray.\n" let s3 = if successors() = {} then "3. Current disc has no successors.\n" else "3. Current disc has a successor.\n" let s4 = if successors() = {} then "4. Current disc has no predecessors.\n" else "4. Current disc has a predecessor.\n" let s5 = if OccupiedSlots = {} then "5. The CD player is empty.\n" else "5. The CD player is not empty.\n" let s6 = if OccupiedSlots = allSlots then "6. The CD player is full.\n" else "6. The CD player has empty slots.\n" let s7 = if DoorIsStuck then "7. The door is stuck." else "7. The door is functional." return(s1 + s2 + s3 + s4 + s5 + s6 + s7) GetActionResult class CHANGEDISC... GetActionResult() as String = asString(res) SERVICE methods GetId class CHANGEDISC... GetId() as String = "ChangeDisc" Invoke class CHANGEDISC... Invoke(a as ACTIONCALL) as RESULT = machine action := a res := RESULT(ok,"") step fireAction() step return res fireAction() = match action.name with "AddDisc" : AddDisc() "NextDisc" : NextDisc() "PrevDisc" : PrevDisc() "RandomDisc" : RandomDisc() "OpenDoor" : OpenDoor() "CloseDoor" : CloseDoor() "ToggleDoor" : ToggleDoor() "HasTrayDisc": HasTrayDisc() "IsDoorOpen" : IsDoorOpen() UPnP Action Definitions Derived functions class CHANGEDISC... trayHasDisc() as Boolean = CurrentSlot in OccupiedSlots successors() as Set[Integer] = ({e | e in OccupiedSlots where e gt CurrentSlot}) predecessors() as Set[Integer] = ({e | e in OccupiedSlots where e lt CurrentSlot}) Error conditions class CHANGEDISC... UPnPerror(code as Integer) as Boolean = match code with 701 : OccupiedSlots = {} 702 : OccupiedSlots = allSlots 704 : DoorIsStuck oth : false AddDisc class CHANGEDISC... AddDisc() = if not(UPnPerror(702) or (UPnPerror(704) and not DoorIsOpen)) then DoorIsOpen := true choose slot in allSlots difference OccupiedSlots do CurrentSlot := slot else if UPnPerror(704) and not(DoorIsOpen) then if UPnPerror(702) then res := RESULT(err,"702/704") else res := RESULT(err,"704") else res := RESULT(err,"702") NextDisc class CHANGEDISC... NextDisc() = if not(UPnPerror(701) or (UPnPerror(704) and DoorIsOpen)) then DoorIsOpen := false if successors() ne {} then CurrentSlot := setmin(successors()) else CurrentSlot := setmin(OccupiedSlots) else if UPnPerror(704) and DoorIsOpen then if UPnPerror(701) then res := RESULT(err,"701/704") else res := RESULT(err,"704") else res := RESULT(err,"701") PrevDisc class CHANGEDISC... PrevDisc() = if not(UPnPerror(701) or (UPnPerror(704) and DoorIsOpen)) then DoorIsOpen := false if predecessors() ne {} then CurrentSlot := setmax(predecessors()) else CurrentSlot := setmax(OccupiedSlots) else if UPnPerror(704) and DoorIsOpen then if UPnPerror(701) then res := RESULT(err,"701/704") else res := RESULT(err,"704") else res := RESULT(err,"701") RandomDisc class CHANGEDISC... RandomDisc() = if not (UPnPerror(701) or (UPnPerror(704) and DoorIsOpen)) then DoorIsOpen := false choose e in OccupiedSlots do CurrentSlot := e else if UPnPerror(704) and DoorIsOpen then if UPnPerror(701) then res := RESULT(err,"701/704") else res := RESULT(err,"704") else res := RESULT(err,"701") OpenDoor class CHANGEDISC... OpenDoor() = if not (UPnPerror(704) and not DoorIsOpen) then DoorIsOpen := true else res := RESULT(err,"704") CloseDoor class CHANGEDISC... CloseDoor() = if not (UPnPerror(704) and DoorIsOpen) then DoorIsOpen := false else res := RESULT(err,"704") ToggleDoor class CHANGEDISC... ToggleDoor() = if not UPnPerror(704) then DoorIsOpen := not DoorIsOpen else res := RESULT(err,"704") HasTrayDisc class CHANGEDISC... HasTrayDisc() = res:= RESULT(ok,trayHasDisc().asString()) IsDoorOpen class CHANGEDISC... IsDoorOpen() = res:= RESULT(ok,DoorIsOpen.asString()) Helper functions class CHANGEDISC... setmax(s as Set[Integer]) as Integer = (unique e | e in s where (forall d in s holds e gte d)) setmin(s as Set[Integer]) as Integer = (unique e | e in s where (forall d in s holds e lte d)) PLAYCD Service class PLAYCD implements ExtSERVICE var device as CDPLAYER = undef State UPnP state variables class PLAYCD... var PlayMode as String = "Stopped" var PlayProgram as String = "None" var TrackNumber as Integer = 1 var TrackOffset as Integer = 1 Sensors class PLAYCD... var DiscIsUnreadable as Boolean = false Constants class PLAYCD... DiscTOC as Integer -> Integer = {1 |-> 10, 2 |-> 20, 3 |-> 20, 4 |-> 20, 5 |-> 20} Next action and last result class PLAYCD... var action as ACTIONCALL = ACTIONCALL("","") var res as RESULT = RESULT(ok,"") ExtSERVICE class PLAYCD... GetType() as String = "PlayCD" GetUID() as String = device.uid + "::PlayCD" GetStateVars() as String = "{PlayMode,PlayProgram,TrackNumber,TrackOffset}" GetStateConstants() as String = "{DiscTOC}" GetStateSensors() as String = "{DiscIsUnreadable}" GetActions() as Set[String] = {"Play" ,"Pause" ,"Stop" ,"SetPlayProgram" ,"SelectTrack" ,"NextTrack" ,"PrevTrack"} GetStateVarValue(v as String) as String = match v with "PlayMode" : asString(PlayMode) "PlayProgram" : asString(PlayProgram) "TrackNumber" : asString(TrackNumber) "TrackOffset" : asString(TrackOffset) others : "" GetStateConstantValue(v as String) as String = match v with "DiscTOC" : asString(DiscTOC) others : "" GetStateSensorValue(v as String) as String = match v with "DiscIsUnreadable" : asString(DiscIsUnreadable) others : "" IsStateSensorEnabled(v as String) as Integer = 1 GetPendingActionCall() as String = if action.name = "" then "" else action.name + "(" + action.args + ")" GetStateDescription() as String = "PlayCD state description not implemented" SetSensorValue(sensor as String, val as String) = match sensor with "DiscIsUnreadable" : DiscIsUnreadable := (val = "true") others : skip GetActionResult class PLAYCD... GetActionResult() as String = asString(res) SERVICE GetId class PLAYCD... GetId() as String = "PlayCD" Invoke class PLAYCD... Invoke(a as ACTIONCALL) as RESULT = machine action := a res := RESULT(ok,"") step fireAction() step return res fireAction() = match action.name with "Play" : Play() "Pause" : Pause() "Stop" : Stop() "SetPlayProgram" : SetPlayProgram(action.args) "SelectTrack" : SelectTrack(asInteger(action.args)) "NextTrack" : NextTrack() "PrevTrack" : PrevTrack() others : skip UPnP Action Definitions Derived functions class PLAYCD... tracks() as Set[Integer] = dom(DiscTOC) discNumberofTracks() as Integer = size(tracks()) trackDuration() as Integer = if TrackNumber = 0 then 0 else DiscTOC(TrackNumber) isValidTrack(i as Integer) as Boolean = (i > 0) and (i < discNumberofTracks()) isLastTrack() as Boolean = (TrackNumber = discNumberofTracks()) isFirstTrack() as Boolean = (TrackNumber = 1) isRandom() as Boolean = PlayProgram in {"ONCE_RANDOM", "REPEAT_RANDOM"} isRepeated() as Boolean = PlayProgram in {"REPEAT_IN_ORDER", "REPEAT_RANDOM"} discHasTracks() as Boolean = discNumberofTracks() > 0 discHasTooManyTracks() as Boolean = discNumberofTracks() > 255 Error conditions class PLAYCD... UPnPerror(code as Integer) as Boolean = match code with 501 : not(DiscIsUnreadable) and UPnPerror(701) 701 : not(device.changer.trayHasDisc()) and not(device.changer.DoorIsOpen) 703 : device.changer.DoorIsOpen 711 : not(discHasTracks()) and DiscIsUnreadable and UPnPerror(701) 712 : discHasTooManyTracks() and DiscIsUnreadable and UPnPerror(701) 799 : exists e in {701,703,711,712} where UPnPerror(e) Play class PLAYCD... Play() = if not(UPnPerror(501) or UPnPerror(799)) then PlayMode := "Playing" else if UPnPerror(501) then if UPnPerror(799) then res := RESULT(err,"501/7??") else res := RESULT(err,"501") else res := RESULT(err,"7??") Pause class PLAYCD... Pause() = if not(UPnPerror(501) or UPnPerror(799)) then PlayMode := "Paused" else if UPnPerror(501) then if UPnPerror(799) then res := RESULT(err,"501/7??") else res := RESULT(err,"501") else res := RESULT(err,"7??") Stop class PLAYCD... Stop() = PlayMode := "Stopped" TrackOffset := 0 if device.changer.trayHasDisc() then TrackNumber := 1 else TrackNumber := 0 SetPlayProgram class PLAYCD... SetPlayProgram(pgm as String) = PlayProgram := pgm SelectTrack class PLAYCD... SelectTrack(newTrack as Integer) = if newTrack in tracks() and not(UPnPerror(799)) then TrackNumber := newTrack TrackOffset := 0 else if UPnPerror(799) then res := RESULT(err,"7??") NextTrack class PLAYCD... NextTrack() = if not(UPnPerror(799)) then if isRandom() then choose t in tracks() do TrackNumber := t elseif isLastTrack() then TrackNumber := 1 else TrackNumber := TrackNumber + 1 TrackOffset := 0 else res := RESULT(err,"7??") PrevTrack class PLAYCD... PrevTrack() = if not(UPnPerror(799)) then if isRandom() then choose t in tracks() do TrackNumber := t elseif isFirstTrack() then TrackNumber := discNumberofTracks() else TrackNumber := TrackNumber - 1 TrackOffset := 0 else res := RESULT(err,"7??") Appendix II: IServer Interface The following contains the declarations of all the IServer interface methods and the definition of the class UPnPModelServer implementing those methods. This interface is used by the GUI to visualize the AsmL state and to interact with the model. IServer Declaration interface IServer... shared guid as GUID = "3CB6F20B-4041-424C-A356-D48525A969ED" General interface IServer... Initialize() Reinitialize() Step() Create_NETWORK(info as String) as String Create_CONTROLPOINT(info as String) as String Create_DEVICE(info as String) as String NETWORK interface IServer... NETWORK_LoseMessage(netw as String, msg as String) NETWORK_Terminate(netw as String) NETWORK_Step(netw as String) NETWORK_CollectMessage(netw as String) NETWORK_DeliverMessage(netw as String, msg as String) NETWORK_ReadMessagesInTransit(netw as String) as String NETWORK_GetMessageSender(netw as String, msg as String) as String NETWORK_GetMessageReceiver(netw as String, msg as String) as String NETWORK_GetMessageContent(netw as String, msg as String) as String NETWORK_GetMode(netw as String) as String CONTROLPOINT interface IServer... CONTROLPOINT_Search(ctrl as String, searchPattern as String) CONTROLPOINT_Terminate(ctrl as String) CONTROLPOINT_InvokeAction(ctrl as String, srvc as String, actn as String, args as String) CONTROLPOINT_Discover(ctrl as String, what as String) CONTROLPOINT_GetOutBox(ctrl as String) as String CONTROLPOINT_GetInBox(ctrl as String) as String CONTROLPOINT_GetAdvertisements(ctrl as String) as String CONTROLPOINT_GetMode(ctrl as String) as String CONTROLPOINT_GetInMessage(ctrl as String, msg as String) as String CONTROLPOINT_DeleteInMessage(ctrl as String, msg as String) CONTROLPOINT_SaveInMessageInAds(ctrl as String, msg as String) CONTROLPOINT_GetOutMessage(ctrl as String, msg as String) as String CONTROLPOINT_GetAd(ctrl as String, msg as String) as String CONTROLPOINT_DeleteAd(ctrl as String, msg as String) CONTROLPOINT_InvokeServiceAction(ctrl as String, dadr as String, srvc as String, actn as String, args as String) CONTROLPOINT_GetUID(ctrl as String) as String CONTROLPOINT_GetIPADR(ctrl as String) as String CONTROLPOINT_Step(ctrl as String) CONTROLPOINT_GetPattern(ctrl as String) as String CONTROLPOINT_GetAction(ctrl as String) as String DEVICE interface IServer... DEVICE_SetSensor(dev as String, sensor as String, val as String) DEVICE_GetSensor(dev as String, sensor as String) as String DEVICE_Terminate(dev as String) DEVICE_Exit(dev as String) DEVICE_Step(dev as String) DEVICE_GetUUID(dev as String) as String DEVICE_GetType(dev as String) as String DEVICE_GetMode(dev as String) as String DEVICE_GetInBox(dev as String) as String DEVICE_GetInBoxMessage(dev as String, msg as String) as String DEVICE_GetOutBox(dev as String) as String DEVICE_GetOutBoxMessage(dev as String, msg as String) as String DEVICE_GetServices(dev as String) as String DEVICE_GetServiceUUID(dev as String, svc as String) as String DEVICE_GetServiceType(dev as String, svc as String) as String DEVICE_GetServiceMode(dev as String, svc as String) as String DEVICE_GetServiceStateVars(dev as String, svc as String) as String DEVICE_GetServiceStateVarValue(dev as String, svc as String, v as String) as String DEVICE_GetServiceSensors(dev as String, svc as String) as String DEVICE_GetServiceSensorValue(dev as String, svc as String, sensor as String) as String DEVICE_IsServiceSensorEnabled(dev as String, svc as String, sensor as String) as Integer DEVICE_GetServicePendingActionCall(dev as String, svc as String) as String DEVICE_GetServiceActionResult(dev as String, svc as String) as String DEVICE_GetServiceStateDescription(dev as String, svc as String) as String DEVICE_SetServiceSensorValue(dev as String, svc as String, sensor as String, val as String) DEVICE_GetServiceStateConstants(dev as String, svc as String) as String DEVICE_GetServiceStateConstantValue(dev as String, svc as String, cons as String) as String DEVICE_GetIPADR(dev as String) as String DEVICE_GetServiceActions(dev as String, svc as String) as String DEVICE_SetStatus(dev as String, stat as String) Simulation Information interface IServer... GetNETWORKTypes() as String GetDEVICETypes() as String GetCONTROLPOINTTypes() as String GetNrOfSteps() as Integer MESSAGE interface IServer... MESSAGE_Get(msg as String) as String MESSAGE_GetContent(msg as String) as String MESSAGE_GetHeader(msg as String) as String MESSAGE_GetReceiver(msg as String) as String MESSAGE_GetSender(msg as String) as String MESSAGE_GetTime(msg as String) as String MESSAGE_GetType(msg as String) as String Time interface IServer... SetNow(n as Integer) IncrNow(n as Integer) GetNow() as Integer DHCP Server interface IServer... DHCPServerReply(rcvr as String, id as String, adr as String) DHCPServerGetMailbox() as String DHCPServerDeleteMsg(msg as String) Fire interface IServer... Fire() NETWORK_Fire(netw as String) CONTROLPOINT_Fire(ctrl as String) DEVICE_Fire(dev as String) //end interface IServer Other interface IServer... Get_Networks() as String NETWORK_GetType(netw as String) as String NETWORK_GetIP(netw as String) as String Creation of Server getCOMClasses() as Seq[GUID] = [GUID("6390E481-FD89-41C2-8552-EE96EF2918E6")] createCOMInstance(clid as GUID) as IDispatch = new UPnPModelServer() IServer Implementation class UPnPModelServer implements IServer, AUTOMATION Create_NETWORK class UPnPModelServer... Create_NETWORK(v as String) as String = POPUP("Create_NETWORK is not implemented") return("") Create_CONTROLPOINT class UPnPModelServer... Create_CONTROLPOINT(v as String) as String = choose a in availableControlPointAddresses() do let ctrl = new CONTROLPOINT(a, controlPointNetwork, v, "") CONTROLPOINTs(ctrl) := true return(asString(ctrl)) ifnone return("") Create_DEVICE Only devices of type CD Player are supported below, the argument v is ignored. Each device has deviceNetwork as its network communicator. class UPnPModelServer... Create_DEVICE(v as String) as String = let dev = createCDPLAYER(deviceNetwork) DEVICEs(dev) := true return(asString(dev)) NETWORK class UPnPModelServer... NETWORK_LoseMessage(netw as String, msg as String) = IdToNetwork(netw).mailbox(IdToMSG(msg)) := false NETWORK_Terminate(netw as String) = COMMUNICATORs(IdToNetwork(netw)) := false NETWORK_Step(netw as String) = try IdToNetwork(netw).RunNetwork() now := now + 1 catch e as Object : POPUP("Exception in RunNetwork: " + e.asString()) NETWORK_CollectMessage(netw as String) = POPUP("NETWORK_CollectMessage not implemented!") NETWORK_DeliverMessage(netw as String, msg as String) = POPUP("NETWORK_DeliverMessage not implemented") //IdToNetwork(netw).DeliverMessage(IdToMSG(msg)) NETWORK_ReadMessagesInTransit(netw as String) as String = IdToNetwork(netw).mailbox.asString() NETWORK_GetMessageSender(netw as String, msg as String) as String = IdToMSG(msg).sndr.asString() NETWORK_GetMessageReceiver(netw as String, msg as String) as String = IdToMSG(msg).rcvr.asString() NETWORK_GetMessageContent(netw as String, msg as String) as String = IdToMSG(msg).data.asString() NETWORK_GetMode(netw as String) as String = "active" CONTROLPOINT class UPnPModelServer... CONTROLPOINT_Search(ctrl as String, pattern as String) = POPUP("Not implemented, use 'CONTROLPOINT_Discover'") CONTROLPOINT_Terminate(ctrl as String) = CONTROLPOINTs(IdToControlPoint(ctrl)) := false CONTROLPOINT_InvokeAction(ctrl as String, srvc as String, actn as String, args as String) = POPUP("Not implemented, use 'CONTROLPOINT_InvokeServiceAction'!") CONTROLPOINT_Discover(ctrl as String, pat as String) = IdToControlPoint(ctrl).searchPattern := pat CONTROLPOINT_GetOutBox(ctrl as String) as String = "{}" CONTROLPOINT_GetInBox(ctrl as String) as String = IdToControlPoint(ctrl).mailbox.asString() CONTROLPOINT_GetAdvertisements(ctrl as String) as String = IdToControlPoint(ctrl).ads.asString() CONTROLPOINT_GetMode(ctrl as String) as String = "" CONTROLPOINT_GetInMessage(ctrl as String, msg as String) as String = POPUP("CONTROLPOINT_GetInMessage not implemented!") return("") CONTROLPOINT_DeleteInMessage(ctrl as String, msg as String) = IdToControlPoint(ctrl).mailbox(IdToMSG(msg)) := false CONTROLPOINT_SaveInMessageInAds(ctrl as String, msg as String) = let c = IdToControlPoint(ctrl) let m = IdToMSG(msg) c.mailbox(m) := false c.ads(m) := true CONTROLPOINT_GetOutMessage(ctrl as String,msg as String) as String = POPUP("CONTROLPOINT_GetOutMessage not implemented!") return("") CONTROLPOINT_GetAd(ctrl as String, msg as String) as String = POPUP("CONTROLPOINT_GetAd not implemented!") return("") CONTROLPOINT_DeleteAd(ctrl as String, msg as String) = IdToControlPoint(ctrl).ads(IdToMSG(msg)) := false CONTROLPOINT_InvokeServiceAction(ctrl as String, dadr as String, srvc as String, actn as String, args as String) = IdToControlPoint(ctrl).action := ACTIONREQUEST(ADDRESS(deviceNetId,dadr,0), srvc, actn, args) CONTROLPOINT_GetUID(ctrl as String) as String = IdToControlPoint(ctrl).uid.asString() CONTROLPOINT_GetIPADR(ctrl as String) as String = IdToControlPoint(ctrl).adr.asString() CONTROLPOINT_Step(ctrl as String) = try IdToControlPoint(ctrl).RunControlPoint() now := now + 1 catch e as Object : POPUP("Exception in RunControlPoint: " + e.asString()) CONTROLPOINT_GetPattern(ctrl as String) as String = IdToControlPoint(ctrl).searchPattern.asString() CONTROLPOINT_GetAction(ctrl as String) as String = let a = IdToControlPoint(ctrl).action if a = NoAction then return("") else return(a.dadr.asString() + ":" + a.srvc + ":" + a.actn + "(" + a.args + ")") DEVICE class UPnPModelServer... DEVICE_SetSensor(dev as String, sensor as String, val as String) = POPUP("DEVICE_SetSensor not implemented!") DEVICE_GetSensor(dev as String, sensor as String) as String = POPUP("DEVICE_GetSensor not implemented!") return("device_sensor") DEVICE_Terminate(dev as String) = DEVICEs(IdToDevice(dev)) := false DEVICE_Exit(dev as String) = IdToDevice(dev).status := byebye DEVICE_Step(dev as String) = try IdToDevice(dev).RunDevice() now := now + 1 catch e as Object : POPUP("Exception in RunDevice: " + e.asString()) DEVICE_GetUUID(dev as String) as String = IdToDevice(dev).uid DEVICE_GetType(dev as String) as String = IdToDevice(dev).tYPE DEVICE_GetMode(dev as String) as String = IdToDevice(dev).mode.asString() DEVICE_GetInBox(devId as String) as String = IdToDevice(devId).mailbox.asString() DEVICE_GetInBoxMessage(dev as String, msg as String) as String = MESSAGE_GetHeader(msg) DEVICE_GetOutBox(devId as String) as String = "{}" DEVICE_GetOutBoxMessage(dev as String, msg as String) as String = MESSAGE_GetHeader(msg) DEVICE_GetServices(dev as String) as String = ({(srvc as ExtSERVICE).GetId() | srvc in IdToDevice(dev).srvcs}).asString() DEVICE_GetServiceUUID(dev as String, svc as String) as String = IdToSrvc(IdToDevice(dev),svc).GetUID() DEVICE_GetServiceType(dev as String, svc as String) as String = IdToSrvc(IdToDevice(dev),svc).GetType() DEVICE_GetServiceMode(dev as String, svc as String) as String = "" DEVICE_GetServiceStateVars(dev as String, svc as String) as String = IdToSrvc(IdToDevice(dev),svc).GetStateVars().asString() DEVICE_GetServiceStateVarValue(dev as String, svc as String, v as String) as String = IdToSrvc(IdToDevice(dev),svc).GetStateVarValue(v) DEVICE_GetServiceSensors(dev as String, svc as String) as String = IdToSrvc(IdToDevice(dev),svc).GetStateSensors().asString() DEVICE_GetServiceSensorValue(dev as String, svc as String, sensor as String) as String = IdToSrvc(IdToDevice(dev),svc).GetStateSensorValue(sensor) DEVICE_IsServiceSensorEnabled(dev as String, svc as String, sensor as String) as Integer = IdToSrvc(IdToDevice(dev),svc).IsStateSensorEnabled(sensor) DEVICE_GetServicePendingActionCall(dev as String, svc as String) as String = IdToSrvc(IdToDevice(dev),svc).GetPendingActionCall() DEVICE_GetServiceActionResult(dev as String, svc as String) as String = IdToSrvc(IdToDevice(dev),svc).GetActionResult().asString() DEVICE_GetServiceStateDescription(dev as String, svc as String) as String = IdToSrvc(IdToDevice(dev),svc).GetStateDescription() DEVICE_SetServiceSensorValue(dev as String, svc as String, sensor as String, val as String) = IdToSrvc(IdToDevice(dev),svc).SetSensorValue(sensor, val) DEVICE_GetServiceStateConstants(dev as String, svc as String) as String = IdToSrvc(IdToDevice(dev),svc).GetStateConstants().asString() DEVICE_GetServiceStateConstantValue(dev as String, svc as String, cons as String) as String = IdToSrvc(IdToDevice(dev),svc).GetStateConstantValue(cons) DEVICE_GetIPADR(dev as String) as String = IdToDevice(dev).adr.asString() DEVICE_GetServiceActions(dev as String, svc as String) as String = IdToSrvc(IdToDevice(dev),svc).GetActions().asString() DEVICE_SetStatus(dev as String, stat as String) = match stat with "alive" : IdToDevice(dev).status := alive "byebye" : IdToDevice(dev).status := byebye "inactive" : IdToDevice(dev).status := inactive Simulation Parameters class UPnPModelServer... GetNETWORKTypes() as String = "{Device Network,ControlPoint Network}" GetDEVICETypes() as String = "{CD Player}" GetCONTROLPOINTTypes() as String = "{Control Point A,Control Point B}" GetNrOfSteps() as Integer = POPUP("GetNrOfSteps not implemented!") return(0) MESSAGE class UPnPModelServer... MESSAGE_Get(msg as String) as String = let m = IdToMSG(msg) return("From:" + m.sndr.asString() + "," + "To:" + m.rcvr.asString() + "," + "Type:" + m.tYPE.asString() + "," + "Content:" + m.data.asString() + "," + "Time:" + m.time.asString()) MESSAGE_GetContent(msg as String) as String = IdToMSG(msg).data.f.asString() MESSAGE_GetHeader(msg as String) as String = let m = IdToMSG(msg) return ("From:" + m.sndr.asString() + "," + "To:" + m.rcvr.asString() + "," + "Type:" + m.tYPE.asString()) MESSAGE_GetReceiver(msg as String) as String = IdToMSG(msg).rcvr.asString() MESSAGE_GetSender(msg as String) as String = IdToMSG(msg).sndr.asString() MESSAGE_GetTime(msg as String) as String = IdToMSG(msg).time.asString() MESSAGE_GetType(msg as String) as String = IdToMSG(msg).tYPE.asString() Time class UPnPModelServer... SetNow(n as Integer) = now := n IncrNow(n as Integer) = now := now + n GetNow() as Integer = now DHCP Server class UPnPModelServer... DHCPServerReply(temp as String, id as String, newAdr as String) = let msg = IdToMSG(id) dhcpserver.mailbox(msg) := false MESSAGEs(msg) := false if msg.sndr <> thisDevice then dhcpserver.Output(dhcpserverIP, msg.sndr, DATA({HardwareAddress |-> msg.data.hwAdr(), NewAddress |-> newAdr}), dhcpoffer) else dhcpserver.Output(dhcpserverIP, broadcast, DATA({HardwareAddress |-> msg.data.hwAdr(), NewAddress |-> newAdr}), dhcpoffer) DHCPServerGetMailbox() as String = dhcpserver.mailbox.asString() DHCPServerDeleteMsg(id as String) = let msg = IdToMSG(id) dhcpserver.mailbox(msg) := false MESSAGEs(msg) := false Fire class UPnPModelServer... Fire() = try RunUPnP() catch e as Object : POPUP("Exception in RunUPnP: " + e.asString()) NETWORK_Fire(netw as String) = try IdToNetwork(netw).RunNetwork() catch e as Object : POPUP("Exception in RunNetwork: " + e.asString()) CONTROLPOINT_Fire(ctrl as String) = try IdToControlPoint(ctrl).RunControlPoint() catch e as Object : POPUP("Exception in RunControlPoint: " + e.asString()) DEVICE_Fire(dev as String) = try IdToDevice(dev).RunDevice() catch e as Object : POPUP("Exception in RunDevice: " + e.asString()) Step The main rule of the simulation ASM. class UPnPModelServer... Step() = try RunUPnP() now := now + 1 catch e as Object : POPUP("Exception in RunUPnP: " + e.asString()) Initialization The set of all possible control point/device addresses is given by the following static functions. deviceAddressSpace as Set[ADDRESS] = {ADDRESS(deviceNetId, deviceNetId + ".1." + asString(i), 0) | i in {1..100}} controlPointAddressSpace as Set[ADDRESS] = {ADDRESS(controlPointNetId, controlPointNetId + ".2." + asString(i), 0) | i in {1..100}} The available addresses are given by the following derived functions. availableDeviceAddresses() as Set[ADDRESS] = {a | a in deviceAddressSpace where not (exists d in DEVICEs where d.adr = a)} availableControlPointAddresses() as Set[ADDRESS] = {a | a in controlPointAddressSpace where not (exists c in CONTROLPOINTs where c.adr = a)} Device network communicator deviceNetId as String = "1.1" deviceNetwork as COMMUNICATOR = new COMMUNICATOR(deviceNetId, //*** addressTable //local addresses {devices |-> deviceAddressSpace} merge {d |-> {d} | d in deviceAddressSpace} merge {dhcpserverIP |-> {dhcpserverIP}} merge //nonlocal addresses {controlPoints |-> {controlPoints}} merge {c |-> {c} | c in controlPointAddressSpace}, //*** routingTable undef) ControlPoint network communicator controlPointNetId as String = "2.2" controlPointNetwork as COMMUNICATOR = new COMMUNICATOR(controlPointNetId, //*** addressTable //local addresses {controlPoints |-> controlPointAddressSpace} merge {c |-> {c} | c in controlPointAddressSpace} merge //nonlocal addresses {d |-> {d} | d in deviceAddressSpace} merge {devices |-> {devices}}, //*** routingTable undef) DHCP server There is a single DHCP server and it is connected to the device network. dhcpserverIP as ADDRESS = ADDRESS(deviceNetId, deviceNetId+".10.10",0) dhcpserver as DHCPSERVER = new DHCPSERVER(dhcpserverIP,deviceNetwork) The initialization rule. class UPnPModelServer... Initialize() = now := 0 COMMUNICATORs := {deviceNetwork, controlPointNetwork} DHCPSERVERs := {dhcpserver} deviceNetwork.routingTable := {controlPoints |-> controlPointNetwork} merge {c |-> controlPointNetwork | c in controlPointAddressSpace} controlPointNetwork.routingTable := {devices |-> deviceNetwork } merge {d |-> deviceNetwork | d in deviceAddressSpace} Reinitialize class UPnPModelServer... Reinitialize() = DEVICEs := {} CONTROLPOINTs := {} MESSAGEs := {} deviceNetwork.mailbox := {} controlPointNetwork.mailbox := {} dhcpserver.mailbox := {} now := 0 other class UPnPModelServer... Get_Networks() as String = asString(COMMUNICATORs) NETWORK_GetType(netw as String) as String = asString(IdToNetwork(netw).netid) NETWORK_GetIP(netw as String) as String = "" Global mappings from identifiers to agents. IdToDevice Map an id to the corresponding device. IdToDevice(devId as String) as DEVICE = unique dev | dev in DEVICEs where asString(dev) = devId IdToNetwork Map an id to the corresponding network. IdToNetwork(netwId as String) as COMMUNICATOR = unique netw | netw in COMMUNICATORs where asString(netw) = netwId IdToControlPoint Map an id to the corresponding control point. IdToControlPoint(ctrlId as String) as CONTROLPOINT = unique ctrl | ctrl in CONTROLPOINTs where asString(ctrl) = ctrlId IdToMSG IdToMSG(msgId as String) as MESSAGE = unique m | m in MESSAGEs where asString(m) = msgId IdToSrvc The id of a service is unique within the scope of a given device. IdToSrvc(dev as DEVICE, sId as String) as ExtSERVICE = (unique (srvc as ExtSERVICE) | srvc in dev.srvcs where (srvc as ExtSERVICE).GetId() = sId) External Functions guessCandidateAdr External function that returns a new IP address for the given device. guessAutoIPAdr(d as DEVICE) as ADDRESS = choose a in availableDeviceAddresses() do return(a) ifnone return(thisDevice) PrintResponse External function that prints the response from a device in the control point. PrintResponse(ctrl as CONTROLPOINT, msg as MESSAGE) = skip PAGE  -  PAGE 5 - ()*Pz{|   ) * , B ޾޵СБyrrnfnfjh1=Uh1= hQ6] hQQJh^5&5CJaJhQ5CJaJhQCJaJhQmH sH hQCJmH sH jhQCJUh1=hQCJ hCJhQCJOJQJ^J hQCJhQCJ aJ hQhQCJ(\aJ(hQ5CJ0\aJ(hQ5CJ(aJ(#()*P{|        ) $a$gd1=$a$'Zh) I Z}<W#1M 8 & 7  & 6 & $a$       ' ( ) C ߼߭ߢw]߭ߢ2jhJh1=>*B*UmHnHphuhxmHnHu j}h1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHu2jhJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHuC D E F G H I J K g h i j m n ~  ³¥¥wwf³¥L2jhJh1=>*B*UmHnHphu jqh1=UmHnHuh1=mHnHu2jhJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHuhxmHnHujh1=UmHnHu jwh1=UmHnHu 89:TUVWXYZ[\xyŶťߑwŶfߑ jeh1=UmHnHu2jhJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu jkh1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu#yz{~ŶūӶw]ŶūL jYh1=UmHnHu2jhJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu j_h1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu2jhJh1=>*B*UmHnHphu:;<=BC[\]wxyz{|}~v\2jhJh1=>*B*UmHnHphuhxmHnHu jSh1=UmHnHuh1=mHnHu2jhJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHujh1=UmHnHu! 6789:;<=>Z[\³¥¥wwf³¥L2j hJh1=>*B*UmHnHphu jG h1=UmHnHuh1=mHnHu2jhJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHuhxmHnHujh1=UmHnHu jMh1=UmHnHu\]bc"#ŶťߑwŶfߑ j; h1=UmHnHu2j hJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu jA h1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu##$%*+456PQRTUVWXYuvwx}~ŶūӶw]ŶūL j/ h1=UmHnHu2j hJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu j5 h1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu2j hJh1=>*B*UmHnHphu !"#$%ABCDGH_`a{v\2jhJh1=>*B*UmHnHphuhxmHnHu j)h1=UmHnHuh1=mHnHu2j hJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHujh1=UmHnHu!{|}³¥¥wwf³¥L2jhJh1=>*B*UmHnHphu jh1=UmHnHuh1=mHnHu2jhJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHuhxmHnHujh1=UmHnHu j#h1=UmHnHu*+,./0123OPQRWXdefŶťߑwggŶV jh1=UmHnHuhJh1=0JPJmHnHu2jhJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu jh1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu!  *+,FGλ衒v\衒K jh1=UmHnHu2jhJh1=>*B*UmHnHphuhxmHnHu j h1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHu2jhJh1=>*B*UmHnHphuhJh1=0JmHnHuh1=mHnHuGHJKLMNOklmnqrҵҵõvҵ\ҵõ2j|hJh1=>*B*UmHnHphu jh1=UmHnHuh1=mHnHu2jhJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHuhxmHnHujh1=UmHnHu#   '()*/0@AB\]^`abcde³¥¥wwf³¥L2jphJh1=>*B*UmHnHphu jh1=UmHnHuh1=mHnHu2jvhJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHuhxmHnHujh1=UmHnHu jh1=UmHnHu c/-<A?=0$a$ 6 & gd1=6 & 6 & 7  & 8 &   ()*,-./01MNŶťߑwŶfߑ jh1=UmHnHu2jjhJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu jh1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu#NOPSTabc}~ŶūӶw]ŶūL jh1=UmHnHu2j^hJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu jh1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu2jdhJh1=>*B*UmHnHphu   &'(*+,-./KLMNQRefgv\2jRhJh1=>*B*UmHnHphuhxmHnHu jh1=UmHnHuh1=mHnHu2jXhJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHujh1=UmHnHu!³¥¥wwf³¥L2jFhJh1=>*B*UmHnHphu jh1=UmHnHuh1=mHnHu2jLhJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHuhxmHnHujh1=UmHnHu jh1=UmHnHu  5679:;<=>Z[\]bcvwxŶťߑwŶfߑ jh1=UmHnHu2j@hJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu jh1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu#    :;<>ŶūӶw]ŶūL j!h1=UmHnHu2j4!hJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu j h1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu2j: hJh1=>*B*UmHnHphu>?@ABC_`abghqrsv\2j(#hJh1=>*B*UmHnHphuhxmHnHu j"h1=UmHnHuh1=mHnHu2j."hJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHujh1=UmHnHu!  89:<=>?@A]^_³¥¥wwf³¥L2j%hJh1=>*B*UmHnHphu j$h1=UmHnHuh1=mHnHu2j"$hJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHuhxmHnHujh1=UmHnHu j#h1=UmHnHu_`efnopŶťߑwŶfߑ j&h1=UmHnHu2j&hJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu j%h1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu# 678:;<=>?[\]^_`klmŶūӶw]ŶūL j(h1=UmHnHu2j (hJh1=>*B*UmHnHphuh1=mHnHuhxmHnHu j'h1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu2j'hJh1=>*B*UmHnHphu )v\2j)hJh1=>*B*UmHnHphuhxmHnHu j)h1=UmHnHuh1=mHnHu2j)hJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHujh1=UmHnHu)*+-./012NOPQRSvwx³¥¥wwf³¥L2j+hJh1=>*B*UmHnHphu ju+h1=UmHnHuh1=mHnHu2j*hJh1=>*B*UmHnHphuh1=mHnHuhJh1=0JmHnHuh1=CJOJQJmHnHu$jhJh1=0JUmHnHuhxmHnHujh1=UmHnHu j{*h1=UmHnHu 78ŶťВzmzgz^^zQji-hQU_H hQ6]_H  hx_H j,hQU_H jhQU_H  hQ_H hQh1=jh1=UhxmHnHu jo,h1=UmHnHujh1=UmHnHuh1=mHnHuh1=CJOJQJmHnHuhJh1=0JmHnHu$jhJh1=0JUmHnHu ce" "$%''9,;,..33 55 5S7d7999:4; & F"$a$ #F]F^`89:;> ? X Y Z \ ] o 4!5!N!O!P!R!S!V!!!!!!!!"""###4#5#6#7#8#Q#ŷŦyj/hQU_H hQ6]_H j]/hQU_H hx_H mH sH !j.hQU_H mH sH jhQU_H mH sH hQ_H mH sH jc.hQU_H j-hQU_H  hQ_H  hx_H jhQU_H /Q#R#k#l#m#n#o########$$$$$$$$%&&&&&&&''4'5'6'7'8'K-Y-----...........j2hQU_H  hQ5_H hQ6]_H jK2hQU_H j1hQU_H hQjQ1hQU_H j0hQU_H  hx_H jW0hQU_H  hQ_H jhQU_H 5.M/N/g/h/i/j/k////////m0n00000000000001115161718191222222 2v2w22222222j36hQUj5hQUhxj95hQUjhQUhQj4hQU_H j?4hQU_H j3hQU_H  hx_H jE3hQU_H jhQU_H  hQ_H 42222222233333B3C3\3]3m3n3o3p3333333334x4y4444445555555588888899999999j9hQU hQ6]j!9hQUj8hQU hQ5j'8hQUj7hQUj-7hQUhxjhQUj6hQUhQ:99<<j=u=====">#>+>6>>>????@(@*@+@D@E@U@V@W@X@Y@@@@@@@@@@AAAAAAAAAAAAAAAAAAB BZB\BkBmBBBC¸¸hQOJQJhQ0J+OJQJ hQ0J+ hx]j:hQU]jhQU] hQ] hQ6 hQ6]hQ hQ5\B4;<<c==#>> ?}??@AAAAAAAAAAA-B2B8B=BB #F]F^`$a$ & FBBBBBBBBBCCCCCCCC C C C C CCCCCC $ #F]Fa$$a$% & FCCCACjDkDlDDDDDDPEZEEExFFGG H HHHHHH H9H:HJHKHLHMHI#IzL{LLLLLLL%M&M?MyMNNNNNNNNNOOοοοj<hQUj<h:Uj;hQUj;hQUjhQU hQ6]hxj:h:Ujh:Uh: hQ5hQjhQUmHnHu:CCCCACBC_CPEEJFPHjH#M$M%M'M(M)M*M+M,M-M.M/M #F]F^`$a$  & F/ #F]F $ #F]Fa$/M0M1M2M3M4M5MzM{MP7PRRRRoSSUU;VV5W  & F- #F]F  #Hx]H  #F]F #F]F^` $ #F]Fa$$a$OOOPPPPPPPPQEQKQMQYQQQ~RRRRRRRRS%SSSSSSSSSUU;VHVIVVV5WAWpWWWBXXXZX[XtXuXvXwXxX{XXj=hQUhQOJQJhQOJQJ^J jhQ hQ5\ jhQhQ5B*\ph333hQOJQJ hQ^J hQ6]hxj =hQUjhQUhQ:5W{XY5ZZZ`\w\x\ ]],]-]]]]^-^.^^^^g____K`x$a$  & F- #F]FXYYYY5ZCZi[m[r[v[H\I\|\~\\\\\]]h]i]x]y]]]^^^^__H_Q_V___u_v_)`*`C`D`E`G`H`````aaaabbcccccc0e7efɺɺ hQaJ hQ5j>hQUhxj>hQUjhQU jhQ hQ0J+hQOJQJ^J hQ6 hQ6]hQOJQJhQ@K`h`cccccfffgggg+j,j?j@jjj k?k@kpmmmx  #F]F$a$$a$ffggggggggghhhhhhh=i>iWiXiYi^i_iii,j2j7j8j>j?j@jRjXjjjjjjôô|v|nhQOJQJ hQ0J+hQ0J+OJQJhQOJQJ^J hhh jhQ hQ5\jz?hQUhxj>hQUjhQU jhQCJOJQJ^JhQCJOJQJ^JhQ5CJOJQJ\^JhQ hQ6](jjjjjjjjjjjjjjj k kkkk!k"k(k)k0k1k2k3k4k7k8kkklllllllllllllllllllpmmϸ驿餟鏩 hQPJhQ6PJ^J jhQ hQ] hQ6hQPJ^J jhQ hQ5aJ jhQhQ5CJ(aJ( jhQ5aJhQOJQJ^J hQ0J+hQhQOJQJ jhQOJQJ5mmmmmmmmmmmcngn|nnnnnnnnn>oDoKoQopppp*p-pppppppppUqVqqqqqqqqrr!r.r/r:rArCrIrOrPrUrVror jhQ5aJ jhQ hQ5\ jhQ hQ6] jhQ0J+ hQ0J+ hQ5hQ5\aJj?hQUhQ hQPJ jhQQJ>mmmmmmm n>o[o\opppCrrrr(s)s\ss  #Hx]H$a$ #F]F^`  #F]F $ #F]Fa$  #F]Forprrrrrrrrrrrrrss(s7s8s9sZszsssssssstt(t)t*t4t4v@vVvkvvv"w,w-wwwwwwixjxxxxxۜۏۜjoGhQPJUjhQPJU hQ5\ hQ] hQ6]hQPJ^J jhQhQ5CJ(aJ( jhQ5aJ hQPJ hQ0J+ jhQ jhQhQ jhQ6s5tLtv vwwwwx y)yDySzrzzzz{{{||  #F]F #F]F^`$a$ #F]F^`  #Hx]Hxxxxxxxxxxyyyy y!yyyyyyyyyyySzYzbzkzrzxz|z}zzzz{{{{{{{{||}}}} ~~ٿٴٯٴ٥ٯٗ jhQCJ hQCJhQPJ^J jhQ5aJ hQ5hQ5B*\ph333 hQ6 hQ6] jhQ hQ5\hQ jhQ hQ0J+ hQPJjhQPJU hxPJ8|8|} ~ ~$?Yiy؄ #F]F^`  #F]F  #H]H  #Hx]H$a$ #F]F^`13gm&,7;>?LMfgvwAKMY]iÂĂ݂ނVeʄτք꧘ꐌh:jh:UhxjGhQUjhQU hQ6] jhQhQmHsH j=hQ hQPJ jhQ hQ5\ hQ6 hQ5hQ hQCJhQ5B*CJph3337$=BM0GԈՈֈ!)ۉ܉෱દ{u{ulubujhQPJUhQ5PJ\ hQPJ jhAMPJ hAMPJhTPJ^J jhT hTPJ jhAMhAM j"hQ hQ^JhQ5\^JhQPJ^J jhQ5aJ hQ5\ hQ6]hQh:hxjh:UjiHh:U%01 !%3PQIT$&WX  #F]F #F]F^`  #Hx]H$a$ $%./?@ABQfwIefgmvyՐTpqry , !&8ѾɺѵѯѯџѯѯљѵюѨ hQ6]h: h:PJh:h:PJ jhQ hQ0J+ hQ5hxjcIhQUjhQUhQ hQ5\ hxPJjhQPJU hQPJjHhQPJU5ɔڔ&@ABGPƖؖŗʗ˗37>DGHIfqӘhQ5PJ^J hQ5hQB*PJph hQ5PJ jhQPJhQ5PJ\^J jhQ5aJhQOJQJ^JhQ6PJ] jhQhQ5PJ\hQPJ^J hQPJhQhQ0J+PJ4X8i֘3bo+,hś&  #F]F$a$ ,02_abj{\ghjpy}›ћқٛۛޛ輲hQmH sH  j=hQ hQ5\ hQ5PJhQB*PJphhQB*PJ^JphhQPJ^J jhQPJhQ5PJ\ hQPJhQ5PJ\^JhQ5PJ^JhQ:  !&/0>+0|\^yơǡạ̃RӺӶӭӦ hQ6]hxjIhQUjhQU hQ5\ jhQPJhQ jhQhQ5PJ\hQ6PJ] hQPJ jhQmHsHhQmHsHhQPJmHsHhQPJmH sH 4#/0+|ɞ7yzɠܠx  #Hx]H & F1  & F1 #F]F$a$ #F]F^`  #F]FETKL\$@efmO  #F]F  #Hx]H$a$RSmp!:;<DEKZ[^`z|̧ϧЧѧ!#fmno乲䓋~hQ6PJ]^JaJhQPJ^JhQ5OJPJQJ\aJ hQ5PJ jhQPJ hQ6] jhQPJ jhQ jhQPJhQ5PJ\hQ6PJ] hQPJ hQ5\hQ jhQ5aJ/YZst(:BCMNOXuv|ͫӫ֫׫ڬ伴䴒󴒴 jhQPJ^JhQ5PJ\^J hQ5 jhQPJhQ5PJ\hQPJ^JhQ6PJ]^J hxPJj]JhQPJUjhQPJU hQPJ jhQPJhQ j$hQ55˫5[z4W~|}HIXj|}Ѱ  #Hx]H$a$  #F]Fڬܬ34~{|}ܮ/ABHVW̰а ?BVZ5<=M^_bhkl hQ5 jhQ hQ5\ jhQPJhQ5PJ\^J jhQ jhQ5aJ hQ6]hQhQPJ^J hQPJhQ5PJ\AѰ;[-MN`ƴ @t]x  #Hx]H$a$  #F]Fɲ$*;D #:?DKMNO[]oFLahhQ0J?OJQJ hQ0J? hQ0J+jJhQU hQ6hQmHsH hQ5 jhQ5aJhQ0J+PJ hQPJhQ5PJ^JhQPJ^J jhQhQ hQ5\:]^ "ջֻ#B} 1[$a$$a$ƿϿ׿(2?F69ILfiy|=KRTWeg#&03>Ajmwz<FUXehvy hQ6PJ hQPJ hQ0J+ hQ5hQZ[=IhK^_++<N_o$()mn %yGHM?Bil?BV\eloz4:DHPS &)7?IMQThltwhQ5mHnHsHhu hQmHnHsH hQ5hQX%1@GHS\fo{ 2\12UVexx4BerGf )7|H}|!WZ%(=B#.59<SUfg1BC]`{ %/hQmHnHsH hQ5hQ^}Cz$V|#O Ic}-%>Par?c3/EHWZhky|-0X[{~ynuwzSYko}?E#*-04:KO`b$' hQ6] hQ5hQ_3CVWjSi0?Uey8svc|@Uh~0|BCU^:@CHsy +.PS} #ILx{ "(+SVlo QTuy hQ0J+hQ hQ5_^grs9jCm#9Nex:;O>?_z"#3^;u#)59FI"%6:CJLOW]pt &+29<?CEwx "%7;@Cvw{hQmHnHsHhQPJ^J hQ5hQZ*RyN,Fwx5\]ww)PbdqBd?Y9>GMTX;>MTVY]_v $*;?FMORZ`pr"%.1X[~=DZ_fmorzhQPJ^J hQ5hQ^YkI`@s<r~(9`_{45b  $_{ILUX|~/9GJjk~mnKLefgij67hxj5hQUjhQUh: h1=hQh1=hQ5hQmHnHsH hQ5hQM #(./@xmn$a$$a$gd: #F]F^`7PQRST45TdstMu   ( 5 Z          M P ^ a m q               hhQ5hQ6]mH sH hQmHsH h1=hQhQmH sH  hQ0J hQ6 hQ6^J hQ^J hQ6] hQaJhxjhQUjhQUhQ;*5t#& Z     9 gdu  & F #F]F$ & F. #F>]F^`>a$$a$  & F #F]F9 k     G o    : b    /GHo0_gdQ d h     17<?HN]`EHnv&)Z] ?IT\hl{ 58UXsv#&AKru}2<cf)KN h#<hQhhQ5hQ^3g#?d{ $?_~.AgdQgdQgdQ2Jm7cdw=fn gdQgdQgdQgdQgdQNw},/?CQTnt #'.1RV]`7:!$179hQmHnHsH h]`hQhhQ5hQZ !P{&Dq9d?mgdQgdQgdQ-?n1=JV BWkgdQgdQ9> +0EIilx{ W],/<@EHSXMRV[^opt    ] a         hhQ5PJ^JhQPJ^J hQ^JhQhhQ5V8Y~ Nu P b    !2!`!!!gdQgdQ $!(!6!:!?!B![!_!!!!!!!!!)"-"^"d""""""""""##7#=#V#Y#e#h#u#|######### $$8%9%c%i%%%%%%%%%%%!&$&?&B&P&V&z&&&&&& hkhQhkhQ5hqD|hQPJhhQ5 hQPJhQhhQ5PJ^JhQPJ^JK!!!"."Z""""""""" #0#7#K#q#}#########gdQgdQgdQgdQ#$/$O$o$$$$$%9%Q%c%w%%%%%&&3&i&z&&&&&'('gdQgdQgdQ&&&&&&B'H'V'h'm'n'p'~''''''''''''(#(*(-(<(C(P(U(^(a(p(u(((((() )+)1)A)D)T)X)e)j)))))))*****-*1*<*A*J*M*\*a*****h~2KhQOJQJ^Jh~2Kh~2K^Jh~2Kh~2K5^Jh~2KhQ5^Jh~2KhQ^JhhQ5hQ hQ^JJ(':'B'V'd''''($(V(v(((((())')k))))) **B*b*gdQgdQb*******++X+r+++++,3,S,z,,,,,,,-M-g--gdQgdQ***++.+1+A+E+R+W+x+{+++++,, ,,,",-,2,;,>,M,R,,,,,,,, --#-&-6-:-G-L-m-t-v-y---------------(.-.W.\.~.........../ /+/1/T/[/k/o/{//////h~2KhQ^Jh~2KhQ5^JhQZ----- ...Q.].~....../ /+/?/P////////060gdQgdQ//// 00'0+050:0>0j0p000+111H1K1Y1\1i1p1v1y1{111111111111111111112222)272;2B2E2\2]2q2r2x222222222222222333!3-313B3E3a3g3{3 h]`hQh~2KhQ^Jh~2KhQ5^J hQ^JhQhhQ5S60?0^0j0~0000001+1?1f11122252V2]2r22222gdQgdQgdQgdQgdQ233+3W3a3q33344G4u44444445=5`5p5555555gdQgdQgdQ{3~34 444"4%4I4M4T4W444444444S5V55555Q6T6\6_6m6s6u6z6[7^7f7i7w7}77777777777l8o8w8z888888888#9&9M9Q9v9y9999999999 ::!:?:B:_:`:n:t:: hqD|hQ hQPJ hhQ hQ^JhQhhQ5V566*6<6i6{6666(7A7s77777758S8888888 9/9^99gdQ999 ::+:K:`:h:n:~:::::::;!;4;=;N;O;`;{;;;;<gdQgdQgdQ::::::::::; ;8;<;C;J;d;j;v;z;<<<<<<3=6=b=e=t=w=============>>U>X>u>v>>>>>>>>>0?3?o?r????????????@@@@*@7@:@Y@]@ hQ^JhhQ5^J hQ^J hkhQhkhQ5hQhhQ5Q<N<s<<<<<<<==O=P=p=====>D>u>v>>>>>??gdQgdQgdQgdQ?V??????+@^@@@@@A8AYAtAAAAAB B)BGBgBBBBgdQgdQ]@j@m@}@@@@@@@@@AAAAAAAAAAAAAB$B(B/B2BABFBOBRBaBfBBBBBBBBBCC)C,CG]G^G_GiGoGGGGGGGGGGGGGGGHHGHKHHHHHHHI I?INIIIIJJ Jh?fhQ5 hshQ hQ0J+ hIKhQ hIPhQ h!_hQhQhhQ5NGHAHLHsHHHHHHIII1J9JNJ]JnJwJJJ KK*K_KKKgdQ$a$gdu gdQgdQ J/J9JCJJJJJJJJJJJKKKKEKHKTKWKxK{KKKKKKKKK(L+L3L6L]L`LlLoLwLzLLLLLLLLLLLMM#M&M.M1MEMOMuMxMMMMMMMNN=N@NjNmNNNNNNNNNNO O O9O\U\gdQzZ}ZZZZZZZ[ [S[V[[[[[[[[[[[[[\\#\&\3\6\U\_\~\\\\\\\\\\]]]!]B]E]M]P]o]r]z]}]]]]]]]]]]]^^!^$^,^/^;^E^[^^^s^v^^^^^^^^^^^__2_5_B_L_t_w____hQh?fhQ5`U\j\\\\\\])]W]]]] ^6^;^P^g^^^^^^_=_B_W_`__gdQ______`;`e`x`````a'a\akaaaaabbJb~bbbgdQgdQ_______``&`)`1`4`P`S`[`^`x```````````a'a-a=aHa[a\akaqaaaaaaaaabb2b5b=b@bNbUbWbZb{b}bbbbbbbbbc cccc>cHcoch[hQ6 hvhQ h^jhQhSo+hQmHnHsH hSo+hQhQPJmHnHuhQh?fhQ5Hbb cc)cccc"d;dUd]dvddd e8eYebeeeeefMffff,ggdQocvcccccccccccc?dEd]dcdddddddLeOeeeee ff:f>fkfnfzf}fffgg g#gugxggggggggg hhhh&hEhdhghshvh~hhhhhhhh'i*i:i=iiijjjj=j@jMjhQmHnHsHh?fhQ5 h[hQhc^$hQ0J+hQ hc^$hQS,gUgggg"hChhhhhh iGiiiijZjjj k@kIk}kkklElLlMjPjjjjj(k+k3k6kfkikqktkkkkk.l1l9lrArdrgrrrrrshQh?fhQ5`Llllll#m]mmmmmnWnnnno#o\oooo,p_pppp0qZqgdQZqqqqqr+r6rKrrrrr+sUsosssssstMt|ttt u.uTususss!s/s3sYs\sisnsus{ssssssst"t1t4t@tCtitmttttttttttt!u$ufuiuuu vv*v-v_vbvjvmvvvvvvvvv;w>wFwIwwwwwwwwwwx0x3x?xBxJxMxxxxxxxxxyy$y'y/y2yyyyyyhQh?fhQ5`suuuuuuvJvvvvvvv#wRw{www xxVxqxxxx;yfyyyzyyyyyz z z>zAzMzPzXz[zzzzz'{*{2{5{{{{{{{7|:|f|i|||||}}@}C}r}u}}}}}}'~*~2~5~~~~~~~IL} NQ|"*-ׁځ x{тԂHKXhQh?fhQ5`zzdzzz{>{t{{{|C|q|||}K}}}}>~w~~~!U((Yǀ6w$b1ey,Ef,XgX[iotx,2Y\ل܄"EI]couЅօɆ̆Ԇ׆&)7;PW'=@HKXwňو܈:=adމ&KjmhQmHnHsH hq?hQhQh?fhQ5Ygo̅*X3L|Ӈ%TuÈ/HUoolj &KfCM~Ë .PQwԌٌgdQGL"%2Qjm|Ԍٌߌ(+EHx{Ǎʍ"wz֎َ"%?B 9:7:,/]abiknv|Ēǒ   UXux h9hQhQmHsHhQmHnHsHh?fhQ5hQV cd,5doÎĎ_dǏǏ܏*9:ÐܐJh#H,-IgȓgdQgdQgdQ:=QV̕Е—ϗҗ$(ghn),MSV\›ʛ͛Ɯɜќל58@CT[gjx~ "06dgor~  hnhQ h-NhQ h9hQh?fhQ5hQXW#DY{ʕ1rՖ7Xmy— OhgdQgdQgdQBv @Mfzњ4PVo֛+XgdQgdQXc"R՝ NV|3U0]kgdQgdQgdQgdQ  #&6=CFcfpv|"%29;>Y\agmty239:;JKQRSTYZihxhxmHnHujhQU hQ0JjhQ0JUhQh?fhQ51ku&'()*+,-./012;<=>?@ABh]h&`#$gdQgdQgdQBCDEFGWXYZ[\]^_`abcdefghigdQh]h+0&P1h/ =!"#$%`!=Sﺜ|q;Wufg*#~ \;=x |E?K{oTDV#"* Ψ0A cAE" q B]D@A0lEJ&*Gut9}ںJULEyKQ)WS'O4OU3e)BW!f8<(L_5#7OZ>3%2*}pk ;D!U9&2"ܥܤ܎p+WWWV(+.F EFS"~Tup}_=PgW9G yjOϜB!Xu%g񧟙|i_oDj3n=^,+|U8vŸ5ӮO ɿw|hɷ)of84by*/iEu>X]l}⼫wwU /x >/MrU='iP4!ۖ?dpwy(^^w\QUeu~~?SH9wAFw|.p/3%6.LoWݓ!akSF-WAeYK)#k ~R.W'y"MΗ=xq&mBO YEbh&Qڦr*s,:C4ն^^OyV߅p9yOPЙW~7D1%F:L ¿e.=.>Zz(R7!fKW2]}U{3~z~s;lGexQLC=(ꕸԷeCz>uIu*~q=3K^>d%6r15tʲ_v t(n"L}8ʏwΏ, vEr:f֥ޱw<֧VO|,YpdctYnė KZ\YUu6J+,i>e闰,=O[y|Y 檮(,Q?]us}oV͚YF9Esfo_xH821̤V-0|{G++WLUw&"Kȹs;o~QJ㕾޲̷,ɛu3T"qtR^n1Yz8]^3*GGxhDdI:̑^tY*G" ڥK5O >ݑOe}rdI=gRUHy9W;]h#KgR٥ʚ'Kud(tqR=l߾]T>+Gf .$rtJ٢l0w6e]iaSUl;n`嬓Ξ@ VWnsT;-N#+1#p,P)dThC?f-T13vsfv+f_E6jK$zB#mhyM5[ћfKzlN]&lLu$:tXO9+?^twwYPu~Ao,~{vTbY&$A,\ֵMa=˃텞,hne ͬaeltKs92Bs kl----f vYKX]i/gwB瞴3Zbo`,M cfAM}ˆ-kS]޶ғv"i7+`_Fi vt Br2//4lJtِڙYT= =˃B$tbU7+b/V-f MܭzhK[J1 1{Vd9bo/nfk-tvz `94,Vۚ:X3Xf"ٚŘ=5粛o?l&l6tqYl+;aA#/DF+mNm&h}.îI7CuA7[ hՈBc5k#0J'f] ]m9\jiVZMiРw$f}Vu;摣 8E3#\ FyG-Knb,+մֱDk KVV& G!cOߍvv<C'<뛪71g?,A'n]muKGD 4Azح7ochZ6`nֳ d_Q N +0MtmatM4ZԕFQ?<F- C odc1c>uHCx2Q*J鴌E|>eň# P-s3;zh+@hxu A3:v<еfux7|WKW~J+XK=c8kPaP2t2z6z><6 XIQkIw4k4I AS:5^{bAƛtzWMI|$ߣX'Ḿ-9}[ӑ \< @=o/݇_!{! ;<߽;@O.}gY2K݋IOvv m|j0gdba3gt?j!t/?{#Y*b)-64.t  4:ѿ!@ED/3w OE<_4-|[7/nE?ho݉wgX z2@rЗ:޹{I@ٵZz4 0gv9#3g4t3gMi}K C(у+wgFR#w1Yc 4>z͘#?Ag( )R|*IE}SQ?|>Al?Nb7g}S&;F?>YVGVOƘ?F}e؄ax?4v>ChtGc,lO]aP d'dB}PD{ڧ3moC0;G3g(^vrÏueVd?ZGb> "X̏Kyί<\]|3AE|i&H!1CxMяy=q o$Dqh*dR1ȸLh) eb]*FQsя(ZQ#Q#jtVCf!L!cb ;%gކ~ ޵skF a0'4;sB̈́;'tO%CRgg,籵5io :4k4F1A_c.op/+<Ř3_̓R~_`|2mm-@|d.yu?_k$~CFci$xzwLEH@OMhXI DkHԤڢ/Xub""z6z&鏧kF ]3*kF ]3}ꚟ Sw~3P ݛ2xK9l1?9h(O|}Ι9oaLw ~a1<ߘƃ|Չ{0h܇pSyH_P~ p'^N^4`\ 3j;:C}NxhN "D8ȁAc%SJ_'>t0?+hOJ_Z-+(g开-ЧlBc9k|kkzHoB~.ʿ6|C}?m{6l.s=E=Eo^N^˷uڿw/K;sI9ܝKZj~v8VChtGcX&b]aBg.9x.g / 3wY[VU{zl(? fM]R鯪-7KjC}Z_"}~~qm69HGRT0/k-zf;yXsŖV' #M˪1dT)~ h%h,2wpg-<_wIDZͺBaκ?2g.N?B}:bM~/CiI4Zx~9yU,Si),Jg.lғ Q۬2=,g}|[~Qo!=z+WK+_ih TC1^c(OgEJ#fZjCjԽJ͠TV}>Jש @gתY[u2k͚Y'va!=+aГ6W{3xg}٤LI85Ƈ*')onVNn\ #8)ߏ VKKJ,lD<aL()4%YLОWFk=aU"t==@׭Ϗ|ijvgsUڟH<¿.NFf37dYwDzpߓ62IJf^ v05w`&+nuNh̝Eet33s1\bl0ӌc/Z+LY+nm1RBk*0vXB$#};|Տ/^) >ʟF1ZkКď f2x9?eN19_dd{ŋ :=빤Ϗ|ijsoV]Soژw=rPs=x_2Nǵ. Z>*\RgJu1*!l~Yn{H\ko^I={ 'y?h'-84kmyztIp3!#>]ws3|>L>Z̿g> 9 >s6|Fg>^3GgNL̆ y>Sq>Sg}333g|>^?gփ<_>s6Qg>Z>s|f̕3gggN3Ro V+Uh+bλ]c:.%LIELY_e],ݟ3}DM~#ϰg|yg~ޤ ړs;_Ly'NVu?ve-C͝/ mIϒÎo4>}v.,70<~\W^ l !4P5C{L{da^R'V_M{hmvgm}bߨe#0p>YM{9p61Cx@ x%V5;Z8u3mpHlgs>?`5= a=n l' Ez}]k?XT䁮l\IzK,_=L Jyb<QA;yKcL9҇aٗ?[_Ya7z]z a7`w%{(G;,ހc{ ~AgQ<2 I .CE'hK`@jeJc1=Nmu^?O`S~x&sn&15~2cw2^2aX@;Vд9%m] EZ{3$|e9%#һ#QO%/:~tKoGoG.IoiÑ,@9!#)U_#N ?3* ߿U?M.{~N~Tig?t+][ʓv; r#]_fV(prI)T me-H`5%1xrc`r26x2=NYoQv+(G*ǂ!%six;ԳmB[Qv~> |o\|ik%t}oAEGg!P Jf&}xE@6oc5v=Vl=VJ".X$}n>Aܰz0AQ[w._^YGjÃ_jWih>/@ w;/S*~[#|ߋ=ʎѫ't֛$կNhߜ n {ViL?h:h7'$jW'& [cULTP0m}.@ٯUV53xX DxkPm==te>&;tPjPZMCBz&mK0M~mCZ^7'huQCj-C\!TRCBՉ#ЯꪐjiBM5JV;'6vƒZ^gZy k@NMI8:Kgޯo*؝~Smݡ<ْCe¯).?{/yo\"Uă8_~]kI2(q].):jC>ݤ%nѦfzhsCGšڒ mY_"X+ȹXn-4gn诚ӯ}#B)gmh诚]]~̈vB̳'UgONZ~Q |I{#),<&^26܏5ա,M(Gkڨ@D'iZiݳϞ}4S4mx( q6uh5.EKCBzM by*J?<C+YІ"]@t\\dۖ\TK/mKP+<<,} AO qS!E(žhE|K2f|=K5'T]^{}K?K;W4][ZQ"V$wyϞ (?{*lh(A1y:)Ok O4wݻݚ*O ^+|˞䥌RZ_勗ŕHK]x tJXߊO%{\9:g@SGU)O S$e}IyIگAf!Qz1M ⥑=<ќPз-`ʟ89G:N7~ps,[h;pv.hp_+0{ʵmcaڙǶʶ%'G*+cfŶ-$= #ߏ #{b(ѝ pZq'҇k"x0z`<ôae0Ya=sⲼ|$s|Ǭد<\a=kD(q}ʼiQ 9Nڇzs=%NUc^'4HY~1+;=06_0C=0|fp+,2 #7z`0z֌eyOQ{W$Lfְb0q,?9E0\*F|.,)aηM=mw=ms{y`|쁑咶7;2BpaeL+Y&#`:T S$,sy,0̃9 Y.)'a$o>e}.\'+|0r,W6o|ݥa~1]y<31 cP1,רDJ,oiNmYMaY03Yh,y1 gH0n|,9{ UИ/E[TܗnȚ5ӽ}İ<0 `.f0/O=PKz ü끑=0C0<0|fLfFI/<0az`d,̴0̃6YSha=?O=x1K3h%Yܾ/5ekR!8bE"Zi'jBI7 sQ޸`x\i4ӍR#\b kV=Fk1e,YVժǙ݂v{NϲEK|5c wyk,!k<>"\TMkxOPgbÊˠn}= kWX-޺nuy.N𠸏:aEbhR :5q;2!(苹:)r[~U:LjIEOd}.Z BEy^Pj2|oj2J :Ep݅p1kو"Wf\j/j˺l]BR%$b$b)p2cd~6 NW? 4wgXOuE"0}_iϊAR}m:T;O Ÿ1q"ݷ.A\Q^W8 7ܮQNZbnnWō7#nm-ܮepI *..f9}Cm vXȄ5f.b氇Ms jbkqskd-gthHVjwuװglæڹlmwY,(`J'#B>6uh]ڍi݄S7%[Q5*mV[m%!}lCkͫhي4[fsb6fck'a֡|%Ρ\ݜ$7Wܻ=98~$n:ߌ-0'ɽdVڙZɆ_YKXck1\n.f vYKX]i/gwOڙm{-K7EfmoevG-pT8zP>8 .kS]޶ғv"i7+`_Fi ܼܼܼ#]h^NYeقM130R;50kS< ɽd8 NJsW70SG#S/w'ZakN#~ts5.4fm.do'\ҜXmk&``}BfkcĞnaAv`J{5˵{;-Ξ ޏ\6ٶMj4>aפ&v]bfʹ[}qmfZ ~b֥boϙRK2mMN#{?jy zw! XMLee:haIjd!C(逛E&fmA<@n~ۃ=oGv2پ\f[DyUӷk{' xZm :k=“H(po +-ߊmmxn߆z-7۶ӥߪަ~G4O5-1l>}Ⱦ6f>-,TQ+z(G#pGh;E!c(A -l 5p:b:|]ߧ|iO3JS>(ϧLrW!syxn߃z~F}Q!C{hBS={@.ГйIb0|Cq6Tpr8><6 XIQkIw488ޤ)xѽ_AH1ޠLM:oSIw1> 4D9"p4ϡh:8#.xn߁zQ^Ի@;Ch0? <Cwx{w>:\Е 1d2K݋IZq(+v#ߑp#Y*b)8 NNgc(K9l8`C)DC9 Nozh:Hbh"(HAo9>zN!CS;?ϭ7xo@ZГ4й3HG Ep74KU8kH8&4hlHnسz:1!EdK=QMch 6&k$! ?CdMT.x u1&"= <pɀOsx>|&މ$=qal/OalOg| G:^=V ҏWσN yX Bl,k3y?9|< ŗ<DQ'fnTy 1xѝFOGb\L6.ߌ Ba;]&ѥb5J55FOuVSb6 fc .ڑw;ُ(|8 N Z^V!G÷̇oA_c.op/+<Ř38[/I|)U|0_l>.GH@.&s!̫.^[$D-@2L#QM+F3!a88XI DkHԤ/Xub""NJsST7E7vdpt:i,[Cbs: Mo7?M9g缅1߁9 Tf|cR 0Chpz68=F'c;x]\tⶸ' o'ҌbqxΨ-0 a8.oQM':QuќDlqq1 tG |^_ߌ y^l3D3r]Խ"FO;>oP*]P`XI;m&l3.N?B}: bVɶ멢v) YҘ-RYʕ,Ei+]'gYe2{\Y*bJ ;_y[HOJUiWv1BaW),cD|Fv6Bj;hF3u/R3:Uߢ?u--lٵrVZofj@j]XHmtJv䃮EpRGqjVpkT1yU'nH?ҨblԢRV-F~8Mjӵi$].w6tRjmThՕfڅJ]R]kpRT+He:M٤QԃZOV]ʢ?Mf7I "=Y~6((VP{Kwd<Ps)k,R>irQ@, 1OӐ'HEkWCRjHP*4d4d>4d%4d34d4D@C@C,4d4d64c#4zА?BC<   IdCCvCCCCT7!b@CT6wCC!iА)АА!BC  9 x4Yh_!BC@C4d4d34d%4d>4d4$24 1jUN6O0W3Ր&eҐJCBf'gd3%gXzJ44M[rٌLϒ5Ţv8m%ƜkJm%bG[pi{Nq`bS!w:iFF{=//_=ڷNy{/} (Q,}בO>CˎcY.=VUx8^鲽X+G7:Ts,?dw3_--wndu*z"] ʕw矽G7G7~Ww[v=xy~2xRPo=Usz?lm}~w q߽/*"um%Sg6qd/udqW~o},ۻ*=^sScq2bfc\l+DkkFyS1wn멘߭ݭUŷF.p%\4=jՂ_[J`>FU1w*s̓&}1wnV*sM*Ǘs0?2S~_nG5Y֘X+~~qo)o=m.evL`y3K*Sp(۽$֘-^=E)y.'nܳQz;3_sEtKQz;&_s_Dye{Cyqrq(/N;ʋ{vR(~ν nڽ#"RwP\sv1(˹M7+{yv pa98gi~7sݴ{5yawN9'Mgi{7usݴ{Usy733ݴ{~vϊwr΀wyn=۽t紻iLv7ힿݳݴ{vPwyn=$sнvDkLb[?~Rgi\q7!ݴ{6v?y`o7KGOs.vvy^?v|{Nvuvډe]1+-RWJK> Ir>#N`+.`QsoMCX5>8'V0.Y`!^j' 7hzDdr?Pv*Tx X46^QsU3VƪH6n*(n Ak.)r-_py?s[v.Gg]faGR%1$dE>ǣ[NsX[ay`AɲJK>V$]GK9(uLӾvkZ#AHv9kَE'FGΑqdjuZK3vȃmgzc8q%Fi}㼞r|qzC_;|E!9OlN)q@E$7R\?+#_үkiB.oź}}[w( OUk>ʗnʙZ]+'7"<_+crV$ySmJJ?x|WRnݺ~ٯs5܏|jSS1[Q#E1vRT:|4e6e+I~69֧%)q~=>)>Y7ңWqhW.Yrc@#^S^+,4x_WǿW\}<;e1G{Xj:mEZS'D3gkcs%ʫ3W[UX s9jDİȐ&}\eu%+^J["F[za=bk_^n3F{UMv_gK?hT34:nmq(zxW<b]{䡮}|9uP~U(^9i9u^,wpˁ.Ii뒕]&TӮ&j[W+5vpW;U\\ϫ\}`ˮP5u Rc]CԱ(uy.)`kM1NIwUa;?^0~6:fj? ~gCo'Jk{;pVC=, !yi{/&)Q$mxGHyWS'?`>P06 &;DX̂dm%)dRȮSHYl& <3 3l3KG&`5*H4W3OGOǗ΅9$Cf.y6;(Q<_=J(b:`'llfhxfnX\U]j)PWA*y:z:t \2}Le=ZB+Zך%]-!Bdꨞn'o80t@7 ] ۅLWb4LI0m2)x'Lva4bb%c2sXZkɬ!9Bf ђ,Ļ"b 8Vo)dOQ{ rK&PYKQh _<=_z*+r*nXԧ h}׆'>ԃSo]24OE/` ګx^*dzAOۃLO-q6tēcoXfo cɼiX 6mƳf2nc尌Rx]Ffcq,C;¡TAu5U if/]f>h>d|uOEchx;iO6v?h 4Oc'hFf(h:OA냧`2}!fC"Z"9x$MGaqh;x"BlCƓ76YtlTX)RVIBfcqp 2x/D"( =LJxj)R{X<=iPh2BF <] ",%4f̚5 o3210-O,X2#1BǬxG# m!xI"L >Dχx'hX|`7śK&n:v >C gx3d='23x=#6×̶mU-$`~Sc:=;n(sp޿{z/W<!f9 d=گůy(Spʴ9m.̃/`~l^<#lU>Gυy0̓Г%)ܢ&}7I-$cOC[hG_ }׎t< ~ϬZ< LC"B7L!t `/0Oo/cX0fᙅw3]x;hoy;d޵{,RK[Ѳd":X 2KFKƓS2+Wߠ]sE2ߐ@_0WsWd  E$*s<II\uǢ9tgZgtfVY7gvqW[kxF[Wk8(Z1x0D<sG0泿yz$LGxX<]<Ow2{#5x]K 4\p[xoI4Rf'N9)Ǣ< 9G+MIIOCf*㩌 {LOE[ yxzMy m)`O2O=̏sX7*JCCC񅚋-B[g!ޅd]lXp)Ȝ"[JI8{a<\]OB{{zPeVx둩GQc< hwAd_c h=ۃLO!Ѧ㙁wdq6MxKMo=ɰ6mƳd6L&ɰ2ex]FfvA8g92d=NmYjh͚Zy~(PP|/>d|:4OEhtۑLGh3k?Fd=/B E{ kxykt (x2 F 7L0پv0 f%♃w9d }xxxOf<4ȂmhxNf;l:AA*Uh)xRYE6(p 2+xB2"fEh{L#v0Zz f=0e/T)h BF!E o2],tЂYsxmN9vE(HX<}dc 1 !^A뇧~d^!bXL","$X#f&wd?{,.Aœ7L.\:r`Lfhx2f iXkhx*V [N58%̎s q2ɖ=w#;߬+G)e4L<&^]d+ OED끧'ޞdzA;'=8>N O=a 6XoKv,oEEI&l"'hK,û2K@Lc6m*;T)[@l>al ֣ó:2n{,-ia2E> g+4};M_3vE cO?}ϟj@5fUѪ⩊*d@ /7L0>t!1kxےiKc `49`XMz@_ҿjsk>TAچ1,$lё{voܹ{(_o+Ks>ԈgPԔ|Q:ՁI]uNsYW]]]]]{}׉xׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅxׅ_\"I:xW`!jhgxI=kyb @jnx N;u5tq!LJO!WP `3$05,7ܔOp+>Ώ1rW>w|܏Gͻx"Tgyx?U8 9|Q\6Sď\#({ܥD{vI S"֟?@ULE5F9rWRr9Kd/=.\sd ϒU3dO NUoh0x5$ [YȴʐBJoU *]܋kڀK#:*M؃啵:>'@7*kuv Զ:V[@{jpjL& xvSjl5&Vsz<UXUɪEEYw"q?FZa{Nπ>>i(W!⭊'+8 9Ү+\~=)H.E@aPH[*!z VM,PBAPQ'b%\V5`-uXmImص4 iQu>>9|})I=pl]5kJ0#-so6js9 ֨9zS]} L@t믔zP]u\KelQo]UTJx|2( W(ӯ!BUu*_@QwyL>t@2Q} \oC{.G}Z&^_uGcq=9|Cw>j=RGZCL}KIjR=u UssU۫pGT]nqSՒRvqVRIy^e+<]j>/Uo*@zǿyq -ZUi=נM܀g@z[ԟ^Gٰ@s ӟ")|1)4P,PY(D>sA S*W/2}Wj,}(ZizfB&ҳj:ūtV˨ZOϨOḓֺ[y~G.ؙ- :Z1 h缯9׷ɺeo0o#n0CBV{(80*0$0Bdm|zh6Wʡf w*sgbK,v9d~ڛz4h9dѰ=]ݼ֦}Ӽ+ޕ-jlTسoltO7G|䟵/md h־jV4ֲ3"r]Nfj-[\vs_zfU5J7mUxW cC$S`sBE=P<='KEpzkh6QУrCL>)>j諵mlvYmv#rR"YZkt֏> Chԁ^]agV{aa7\p &zY r@ICͦ=9Fl@7tC+D9eE`vAl㰏C![{;l}iВ7'D.s|L<0'윰Fപm焂<Gr_v `N(UQQjƥ}T#3wn 3wX>v`d74;0se6Rzesr{pz mG6<3ANϾ@;m;8~и_mZ ./ߏ ,vH|Auj(Q-Wdk;:*CCb;(F}c|JwUjh{QXl;~}Ck7qiC]Ʃ}T/o{wYo2r7͒fJk،v|s-w`LS3S|v.Wބ =f!|2r+ɆWVkk+h8 ^1R51J}{◣ EI%D/S>;Gg{Ɔ'KE;!WL`9C:.zZ##ƫ#v#A3WvX<^wAccc=8C垣fܓ{nP޳=I%1#umXGs߲}%+TTwnHX[+ʗRw&ӹ|2*׋#Ey\G ǐ|.>'<yNV\xqV[sE/\ 1i1l4AAMU\ua !VsaZQgD~yqqunzhɟfbRV-d7NUuI=%̴FRf'$Y~qHuZp˼dDg7Ug]XR2x86 LU. E~9KcFHͷy{M뵙\63Or Wh g=^Hp9LOPrKv?R''giRKϥі怑W?%eCek_l_d=[V%,+ d@)枨m6;j"jt]~_+vꡐ.ݟӶ2I1t[s2 shk;Q͏p&@t""532՝Hv}CI Tw{v>[4jN@!]YaELaF߮ၘIgUqN1fv-Q-$[pYGZqn#"z8ŏ?&fY?Ҋ<3~ĮV%y~(YGZ7;7Ϗص5~d5~mjYkݷ#·p>!/b"?iβp,[,VMnI7WVMsnbvܤW͟tsnxMM"CqnMlŹI7=ΙsF/|_ }/$9|~N|C8·p>!|C8~NEfY.L}DyK _Ref511556901}DyK _Ref509221210}DyK _Ref516565819}DyK _Ref509291474}DyK _Ref509221210}DyK _Ref511556901}DyK _Ref509291474[Dd 3'%0  # Ab׋[ {æ`s&HIi n[ {æ`s&HPNG  IHDRLdsRGBTIDATx^y'Eu3>'yc+ /ƘD͢1 D qCAUseAUqMyoΝ3g}NTukU7@@@OOYE{?/5]2  #'pιl%M}>ۑͪUd`dՖC__[lWijKB$źJRposlފsۺ=z6.m%Bk$.d$4t, /mثAV6ʠ."ٷܳB .s:J`{\Z:tOUiw9oJYl6bܼLot)lBLd 7!j3^{Nr;=Uq}osw˥o kq"Z;7曳Uڱ "mCtA@`Vٳi+ Z!]]/Û'i_w6Žg|e'?̟mm?1ڌ?GgGw|$nn`|x߼]޶$˧>69:Ew}۝6^rpǗNmal୷_0)H[ ˰  sH[:KXi}&ϯ7qsOSZ}#Vv~z)tQ;mJڇ \8 K>s;⒨өGӎ!w|G X3>D9C;=@@7 8{ /i[bݺYeme )6|>LgxVmgXe^wo>D&uum׾>xi^s|K˧Fuvwջ9}W+W{xY6h3o?-yҭ٭vG'7ʹoL"iE-[ݟ}=8[[zYAuwg32"Ҏ@tЃ=u6u^s괣{N=u _y~B>bHy~vy4-٩Ԝ/ǟ߻ItKhfUϯgI=澿^u5FD9!`s -M[{nxQϯu-f;lO_~ϯgp9'Mg  D@ߍv 홳QS7fm4 )̓ R!w]:[1 Ja̩GJC׍Oϩ_Ly' 7h7TDn6y4vͲ?~ٴuwo!<.Cnڼ*γ\nhWˏsntv}G)_t{w&^/= ͳ[,;~  0ϯ9z>bqo~q, sNYoy{doʫ>InA:;f;ޠ1-3ݗgbŭWY%٪PY }1juռ}oNj19tX;euGu#t}kI=7@Y]6+Bg/-ž#*G6!V#'k׮nV`12]CסO;G]_ohYB}(]Gλ`]oJw_j `0WPi9J {ܨ=@@@rÆ+=(M^0@FJ   Pt4a@c@@@4(]vt :L@O2   Y~|N>,;ƗV@@z&:+Z>"/a#OBϙGr   0I㲑0 @@@ @@Y}eݜGw3΁,Nj*B bZ @@@u$]m=q.Mj;(~Z>!mDE }=<\;   Н@8[:ݦL53KY{~%_0C; MzItӧjunhOK)/Jd7=Ke!_}fi ]o\7֩ijj>btv;vHSt--- [:@mIӵ&aGbDѰC꯼v  PsguvC%Ӎ. d@@z 2.Ys?o|&tm0;   du=/.y]#yڂ3)Iߪc#\!A@@7ui~pZ=uG˺\0sy ڏ_'2S2td\%+n]'6zfmdz/s=m߲m]sf( K+lSov\>ޞ=VjK2Vl 'tlh }ܘp0CF<Ĝ.9itt=Tcձ{ngK-HB_g9g-ߔ7C5{8Ӡt8;N9\}HrW[0zx y^D,RnV4!'1rJqIN)GFE6k߂}ݕNA@xL~@F@=-xf3:v9͠8[FO0 :Ν, 0v>]d |dyc cX? 9/Fe0#y$g.x vI+>GC @rT"fwj#i#E%X{bY) ?+/& Λ{*_nG~xd!.{=ZŵǘYVttcA-,[mPvglmn@MmiMtT{ 0 5>F_j6=Ԁ4a;4ԮҒR(iBQ@qƀ`;)$NKx@<|5U=|4+d|N{W3 c'V' e-igv=s AOiRFIN7.=گpt@|F* h%7@@`Dº.ɞGYn{[gZ#*o   0mQ'EN`jHOmӊa@@@r9?M;>-,@lѿz}H[DTЖ rV\cE]SM9=B*ӻ!3a=TWm-L@>]"k>V(;q6=^A#oTÊD ?$z򕥲UX^Y# 0?Zz94rOK7{ZJ6`@`[el$-rLrJaHH-Um;v^zl\'wzhFXTDR:/`S l*Ƕ#:  @)]=.N;v珏x+w[OV[ANO;&$1^A0A"PV5JA{ձtkoGbeCBȹ7K֮ ܖ2 0o?D6o7g=Y  zC@@@'!$  sL>DžLt}rE 1sȓk`\^^>ӝIҺ yܝ1]6 mtO`FbLM   6KϹ k   0a|XX;dq/9x嗷. *\Xy;y0bs=R `?tGyn95{6I (_oJ9G5mNZS$?d Q/:L6 cGBË:c<'\6~{&vwvma]g}vNwvw5%8.6/x6mX;n bng?6B>YO|y3(۳>N;vBxcySOc{OyړE;/mO}#y#Oy#x{6mYco䷆0 0~vZ7GW>}FfӦMK yG_ p 12vn1ыE7v(Qc~`.M}Ot]E;=Kݺkn"!|ݭџウ37FcǶEsw*_w}Ys s}vߤMoFji?wh`*}'Io~OCڃz@r{ yvE.N#*$2v,ޗڇ7O/I[Sn7?YFȹ%CK.moi,ǾVx;강MCmq6B-rie7OK;]S7Ҿ/mv箫yvvzol5m#< wܯ+юH:{x}s F;Z!E_4zLN:=9]u݀ŝuy~Wd(Bv^zC9x&|Y VƱSt䜘9uϫE= CK_ifgu2ţ'u9KLt%|)Y]u=mYtn;izk~z0V6 ZE$Odzgν Z@iu:H5VnvZ1Bkk&f\| 1yq :q,> ϯ;EH=hH[U?~іf!o,_:OFi\[h~剏M “2n̵*|S2ΩtL+W}\/Ob(xH5ĻE]Ftgx x=Nu7ᱹ|VvigYxS<γ~4[X:p=F_w_^mcN7iM馷7<ϯhM~2o֦JPKI]soݤNR(97Γhm?Vx,xY7_jG$ɢW~΍$踈:Ⱥnus<.d~]Ó:1I,ZOsn|sQGhz+#@v^1ǫǏ>H #mƄϠY1( -[CaD6QYWUh}OyWq$sno2fxG?Dy4Y7'gg֥qe^Q9FΓhAA_~Mu`2N<&Ax{z꺳s#ijӕs#iusQ=i7~ȍ6-Nx{ߧS/4'iUXvrJt{ ]*>X 0orX #m` *p*1F|7nP]Nsc??`ۼnq} 0c/ 쯷 0@xVN'*}J-F!c()P{|C 1%z 3A7qJ{ Ɂ 'uQAA*|3 6t~TG]  ( 8"=FXa$$@! gCBF#E@s~?&:RU9N\KG7?H}J63%==-R{k`uxA[bAGWcқ O//rzフ   0II+2  0sZ6 Wa6J ߤ W?ǹ+GF T,6q=0/fc@`6nX/eGv^H? tO#m) m31~ܱK6 s֭[o>} :  {ކu,,@*hKG_#X\\ċz>IRuGPYG#JSd-z$ VOUjmd+#D}s^3h|J̸wz$9 LuBk=lBOkЈ0Џ i$GPD":."@~]|SSr7h@` kD oxvI=mD LUK(};CU#p%1.,pr}KRFM J{%7@ @f]Y-Vc/O*mh70g9'|^ ҙ6qN1~"Iħ&Yםp=} 0F) Ŏ6ԍHK"XE"BJ=Vqn.2A`NS26IE"Bڃ4.n{Sfm|4ރ} s $ ke/] "& A]~s޹CZz:)I(An02rz$>_d@GFv*YK .B7~Zғ.Mu$ІE Ȭ*k98cUD ,`Ĵ"qCOFћ:|Zn< _wCc5lƒ@^t]W8G8cYm>`HO*y5t N9FYDlqNx3mJ[9AVzSoALH=J/Cm烞q{9eG7bqV"o麧Ԩ8t;bl}Bk.d)A)t Y!F>3zZMLN1+I~sŘUl.t/@ xG|tzz^;=eRM]kf z ŋ|:Y  vZ`^_ uxg\Bt@@W}G^tVNz969L<'4`ElȐ;2;XCN -sl3Dr.pXF1q`7C1f@z0IH aeY]we4y  ]tw}ȜI{4sRFmaAOe4Հjn]C1d8 *pː`{Q85"vH?ێ-!$"Y>bLUNrm;GhȰ&pZ" S=50d#vkj+h&q5̺>jp@@N`9P#WM_ZZZ{ ߻&x1|Wq{n.p, }-]׳ F@}Nk:JTt[ $]rG'C:]q-.a|sG84.bb`eΓX7   0Et}ժUMN5H;7қeeG2¹0Yǃ=xK0g  uȬ랻)EalSxm9E;+shv`@'YFکԟMX}=4 FM ΃@f]/{ڲgl {qN "ieWHS '0]ˠiy\U.zNhu ށ.j\ނ@ u .31Xa³ 8H Z6(t5] ROwǛLbM"Dǚ &PPpm%v.,/sFa vî);S"EbVCٹpS:2f9hBTC  Dkm+񧤳qumEk8%o0wjVn?=ld!o)2Rķ95NgrJǷKVvS*,@FG ; O6Ev@ᄂ:毂q[ 6 >Os ٯ@UD   0b_qu0@Q%@@@`:)K@@   0%r  ut9:Lt}:etu@@C>DN@@@ /j Ks?R }%]=7{e֟;֥J>{nAD  #&\@8y    @3Et}(H@@Hy- Ѝ@zxyfogG# C`ڵ{ RVoʣt+  ,-->@y`6]E0y P[hqq_ԝj%@[]~v/܋3J@+) =Y2\KD!zU3O<5<L@.]Ϲ~>k@H>(RiS+I)wnӮ<ݸV9W ?)[rv`4?Fm TB ^Iwcf Oqw) (@ 2'K$qC~ͅi6=4 \K17 Ȭ4.SH;ɛS~uyb8h ;=*$#I8WܑT dz[ `oۍ{'!S_ 5#\sqUx;^uP_/r獸X1 dTTYũ%# jvl'yi"yqL+ȯ}rZ4׍<{?BݝB"`fs8c0ÝhE/L PDrEoReY%qu r%Łq)qa&W-=3Vj3 VL9G0 P9sɿfe1>jC7>p-r*poXHpT0Yz:@0,5>j=8ﹻ٣v`|ݑ`=8$@nmYڲ3 1j`~9 dDz|Z1j#5 5(CSα,MQD @}ƇDkeG-IF KM=ifB٣Yybk Б*AwOCvL{ &}{nEvOZ}ϭhҽBs~9 m'b{o'K r}ϭ=#_:#y??,}Q7"BR)bE@`Dt=d^Zt]щN( 0C, #cllR{u >Ç>7]GP_/w;U:Yx|NlH |u)t]tBF<]h_7%=z 0&z'1   ~u]K礜'XQ002뺼( -ojm1WUV?Z5"[+,d A! /<usun4 ?u>: 6%y` 8  ~}c=:1RýR'%&YYdl&M.窸y&~sJG=W}C>c9;/QWV|d4iɈqBK|n:+,n4?L+[->v-Un95[;=d(x/V|tݨKvd p /~UL*ew!]t UH_@eTu(x5c[UmIny".=$=n#Yi.4?p AMKYy]\Z'y+X0Xo%Y7fY7'# &䔽Sgx|~Mku7U4K^`@'PDu6x7n-RC---!,kQ =c3]ݒW Y߾WXc#d1@vf$Tz?@o^|\G 0 yI~>>`ֲ$f? CN`ى`pժUMd<1CӒ mޑ[3Ix,9,v.2liir\!I7u+,!0&]@EMdǢ.R-hG6wx;ک*e: бo&*mŅ\BRvOEmb_g͋ӹ/@>Μ4ikt]#N4rD.@ QK7o`n,5Eױ'E4t}Hj"4B.ǵAȳtI8StS,MT1^5w$]AT87WLV&?Y'}sxtkvAK`4sC96nuԭ9Zx4jf+X3p\Gv…@A+X,0 |M-7y,Hu.@kGV}uyK w'8!yV9?rڔV^RgGZ#ܶ5J9^d_XXhq.M|"0L@!^uT}ؑa|ٸh0" 2ugq>ka\'Abޏiղue @:̜xt92*nFJ]O#\ @D׍H=XAS1VF$`L̎G04i"W 0-sڵfZxOBX @rPe=Md,ݞ_:g9ϧEkxϯ+'io]Y4 F*&V' !c@@]%݂}:K l0误^'Uř:$©cp~gDsL 97z >$z<֤"zE=)LZ]@[.%U/0' >i5mv]:屓V%zm^`~R Ђz.yf߂NMy­0<uc^B)b{u#c&E=כi%v+gtԑ"0'(7ir>Ҋ @ Q>_B+@`>B@ u )iDtt1B)V~jӏH@ߺ]uK>pz&2z%>BNr0AB}: WIHQ@ @ߺκ+! x]ϯG CIsͯg̩(1I#1 u owLA Ho]io?y,-[Mrk @GԳϯg!Yw&We7EvJ g,W}ys0޶x2>>WE^UqJ (eX{6GҒ0vѐ`ʡ!h<s6㷷Ƈ/C2Iې|ehE`\>0 NxONȶ,!@Q\x[\uIہ 0eM o{ntר\充 &o[<_GR]% y @׻C׻"Bu^"  P jҧ9`q t}4EGA@@ HD   0 zh@GSTp@@AD  !]MQQ!t}4EGA@@ H ;lI4 )i9#﹕+ X&Nn@!d-A=7?4|J\}](6A /C׳:t={"}:K l0uU؂\sى )ƳY6ޱV*YF^,诗icꯟ+A 6A@@4NuM6E^SIF<8 &SV(iuxd {!71QOϹCnxO{⢿[(诗Z}3:)u ]ϥǹR]1ϯ / 2ί@'0u)?&Y7]7 *YyoJm%yB^#s5[b` S \\v%sb)L$e'; ϯG~}Y@`(E@={@snTA%Pc}X"H@@@@Hi(G`ڵra"PI׍w$ Y=x]d)#SsNF]wR...+ףsxίs)/E9$ T_˘F?Ss~E=4ʫtiEKA&',t}J2:×t4Hn^]yN&GpuEޯC\ [H !@x4B3>o5?+Oβ&S N  NEt]>79Wߝ$/Yꥤ*T0 5(5gߌjhTrUCK@@Ǎ =݇+,6#Śz2nk;:+,t CO g]O[yɩhaO(<]jHyp0  `Rmo_wίۙV(zZ>íD`xuz>giJ%wiI0t]F}#{+w03ib-twgbE:{o2tNc2esĊ)]6{^`@@ 6Xyi87ɾ=eHg"ʹrCVn|HiՎYH8b@ n_'](&3  MNmg*ឣF1 %Rz}Qk3N_WGpm%޳?R^{xs3V̬$"mDZ,-tɡKB$`zy?|W]w*!pH׍./N6DŽ4l]StEwc4Y62*Npu >$ ԩ5k:mKmǶ&):O9Su&T CT ~t:wh€y&yACJ?`AtAF p} 'DT z1]! Bs]e'-VzIIntJ+Y;VLmcm!<4 n 1b\܎ _q$ᓳ54D=עsH@` t.E:Ao3<7gYp+/,a@`tÏ.ҎF>:SaZ2q K.@2'CDS]=VZEg.\v\>H${#lJԁ i6)YFD;Q#JD|K8b{hチ{x7mڔ`vkt&'gKQSgs|ricڠXp®6bEȩ(hW;PbTE`4^i;cO~I0W a7Ue1ZӍ`4A Yu瀳mp$si:oDS"ۭĻ{:y*~Psit~ ֺ;YYIqREOىmB0ۍ#vBfV̺!%rPXg Ծq= MRm&A3zSd;;i #긥ݎt){0y]bG & Hz9M˕>.R (ǥG8kT7"W,;s幻y*L9wJmX7ֶ:NEFVgJ44):(np@c1~ć2]EO2<#;`#Z|. eb->w% ĔG7|Oq!y_>GZ $;1:;9 d5Ǭ'ɇ4a嶅~',hߍ7n'v"vg>G@}q*>\X|DoOݰ`$!qyUU0ƨOCe[3Zkycka3nxCܱ{%3fxUY tu hGy9)z|;, ;3NGR=sOe)k5>||HZ8eL=7MC{%i9-KX32Y "ٽ=#+ykz^5Cʝ"S]t* s%Y4k*CX4t ÀɩZpZ!@UFUQs:|K aXEi 5Xl5Mnjx 8.EB 7 *XƑ_e R0MF֢Iw7.=nFZwȰ 02rPXANfdJGljgV0FZEISF4h{ڂ|tk[:ni @ l{LU6r։.&,k[|MŠSIVb[0  @Q1ev32ͣǚt"3J]!6dFvsa^k@HpXۊwJǔsqu`jvl&m 8|7;$Ϙ҉aF@rȬ1 Hmۓv#6)j;yH;UIi'EŴ!$pBSK\$dX1U,|(T0  02t)ˑD1`Rxq?gѭʡMfy'2[;эkMvx0Xgc5Y,4U>GFu2QQ9-p<>_`@&vZ81~yy w(U=V Њ@﹑V 0@w:ֽ{0ԜDo!7%$GtrW   BB q@@@N:^@fzNf0 JVg_~]O- t} +SGX?b'Ke5@w+Q;Sّ@-ϯC;d?ѡpΕJ!]\&/ШV9oM uw/ XZ@k) XfϦDN5H;zk;Sv3+HNf'd#^yψ@w>B׳ *8N;ԧV Oz@b9,EOS(; JXHaF@%hکERbr&zy2BN@ד A!v60MItiìg S hxߞ,`d#oDK[Q B h}XIS׳)t|9&MK,0ڔ38Sw&m(ɦ<Ÿ 1Q )Ix5ZZ<8f7mڄ iQxӊ܊.x-~[F]SNt]kORCcM!<9xu*-b175~T Quip9axhJf$d=joi%1psl""`z.KPM;Z9d;BFv-xLvmٟHAL<^b~z 0#рS"1j㉕,҄BN7brd`PF8Ŧ ʤ{L&Q0"0@S?k;ǓĎ-Z#bvcϠߚȎ-5\E xDϯw  | ѳS^0_@a@j'?R{N/(%׻>H(I,[i4lt=Ũ)_g1dܠ)2:)28%t}Bx&\qi @@`> tꯗb@AI;& ؂B+osGvcx!0 N@f:1p@!u  Б@wLA'`1^C%]%p   P?v&f45"iڮa8 P@']/%usm!<͍+ @QC@@@`:)K@@Ϲ%% O<k{$@`bRs@v@*KKKMGC3 Ѕ@Ls?]]\D\'~GCu A ]Fq#S#]ZA~@mwUtA 6g*9ydA_1@N<~ꩧC6hub}եϪ͚ʱ9=ko{>;f+vF4-NNrfo+IpV(yHMɦ$PmUS\6/_ovbt׭[*<\ۦ±YOgB3_BMs[]mҍ!]7CY͋_{E=R#ytUxX=EV~;t]铴n7㯋k8Mc _Y}u=8DgC#W/ک /x6e;%bqgHI}?O|[s$}ǙD='{(O]vjhg]vvqvzoy.eF;<;5 msF9Og=Fyyig? |Y=g>qO},mOch=Ѽ=I#O}#y{!I{8_JEګugCܳ7sÞ{!N-8]q1[?uqE̞wOwMώ}V(UyZţ/^p9mC.qҕџZ/xmFDw.jh'FI)nvDڵW]}Ӻkn#Zڗjo#"<ݍwF;4/QnNH)ͷC툴>Kӟ6>y=ҶoP0vRtoJ\uڿofԢNhvRtk!mOrN>oYOhv[ms1AޅÞFwl?c??Gȏ6|юkyh`߸=^{ڃלk|wSw].yKv46\/x+vޟ-tOpM?7ﴝpf-]o_fW>\^mr_W/_x%m~~W^?r?>K|+>{19,ݻ[u߼>F_п<[:-F:i'-gYOikvkv?Z޼v9VO}Nr wbwY_~GǭtQē7o|voHP;4Pqvlu&f;>׷oyo^v{f_ڔgxiӟՇϬyVi_tn?M`}bE;]}O_i#|gÄ~ >{1'Ng3_N/}^z ;c&_B_ݷK;ѿ}1}^S/_{G]G{1;f}&KNu+Us9oz̺7#"#;w6~.o ?F;o}J_\-ą~KҎO]ͿleIorv*Cs3&zlsuoGx{DbK;i4嗇C~$dYYR>mdzbrD׿ݟFqxz,`DߍnJ"cCУ׼p~pL_KԜ7כ}AOq=/^/g7Nao|5_GnD:}w?}ʜ, ϫ{MjGrosĚmGnWϒK0sɊ9:{%9}HC?q:ҮCnbNsci7ɢ9ÊN?^1g$!+wy2KNf ,'iKQ,Avm4 K>(=u {rW4o8@=g_ 4(j [M)Vz<g97网';K?i;(OO4NbCOS4/^pw< zԍΞ}ig{[|_;;)M8piݜ>iݜ'9 4Nyϯ4>}#M8X{ߙK)vZ7~sw}sw7b FS4/GξO^=F`=S7V@f~=8ίKt^ `뺡l6T}s%g}s\?c~V}s zxε6hfe+ ^"IϯLب/'VϪ rv@'y[0ֶ[uZ9ސ"LQ\`I3X h \l091j#Ъ]u/BW]"=8ʑ9e3lmp :}DŽG: D2:ϏɒgơT 8ã!SO~z뢄F D^1 ](1Ua*'y[u=*'@@@`@砐E!]FFA@tBNoZNL+C'0/N74 yi*ot+BR3)t^tm񟕔e'<-Ji@C.+}U ̑}e`ng]sgǰfp>@4qD#]o|o.2ڠǚYu $8}ַQ5Gn4t+8ܱpm?|lǬ!:d$8\#])Vccx{2JQn# D7h!>ou>W~nɛG9Ix+@ۆoixOp:u^>`CHk!ax9Em#qi>vrgR/c㒨K(BHdX>/> v[!.qjB  !]NY"'   ]GXE4]wHy:Kt;p @;KKK}\Nɺu3gyz$DyY4.X$邝όゝRU-KOҌ-@קTtD^1yLx@mu@PCtrW   BB q@@@Nsoi,_cY{ yNFO>ufƕqyzBZs^*פ݃w8ߗ>ڪƕqy۪ *{i*/S  |m=ɯ)FOI@Ł<d#S铯kͩb2uEkgdՈI[t`ciF궧.Gh[Wx9krzY{#H%ZㄲWAmP=G)gCO㌳ֿϣ( bԞG 0"h[WXXuγE#b咭|U&cS ;E#67<16G>NhRvQh['z(oNwTq=݈Uܫ k'(Z %J>ٲ,#ud;xC%OtlR\y$nL2 %бt^-ҎaT -kQƾ<g):K'[.jsL#b0\Mƹ,FIq@Կu=/dT&䔽S8dߊoo۔ΑQ vK4޷ɄiC<626/h[_s|!L@V[C|ㄪRZ2uBehH,--lT˧rGd:鼬]"SPCȸr4.o_5XݗD]<1HrLN'^n\91FaҚپJwC@B<&;[CLD@Zs?83>?,VmU.Lɵur8;p-y Ϲ+9fܩhD,@mSUI]RM? ],w=EEme\9 i}[ˮ/n;Z KSS% o33dO'^eO2BWBY(G`4.r|,El;yOe`Lٴi>XO[٦AD,L ldlKya&8_Om{ UzoD%$ d'T\L $/Z',2cE=M`n:(f$<{Sj['7uG"[9km*(O@(dF>n-ʮN\|DZn>}s􌇧9O*FN }i> #V鯷P{ i#VU(S)x̷0XJ#3|(vlA=4==f\D؂t0͂%u?O1q6LH'35xK8tդ Nml't?Q麸kt/s$2ީ`"yzɃY V =4gDfD0-<T@i )F7ZE7賄{qs7'd02Jom. E`u]wy쑝i wRGHmm.q^]'S,Muw<>RֶٍI({r̬1Ɓd;&\NuqU$JT>^6Œ`NۑrZ:`li;g=wd3K@(~+#;d<1`Fji9ؔ.mi9J6FN(`#&v݊6>Ry:W#>ݟP7$~H`( $|!$$)awѤ#LDŽ"z?|k"P*wK Is0 P'~ɥ*פ݃wÞzEEmEf\9 i)|ϭW   PTD ~etXE޽U#pɐY7$ md92׭>o+AD  8iO6ycTrco^?=}Jm iWA~@ד A `I[@' E ] E1"*`=*^6!Gmә۴6NFPk:)9hXh?p,Mk!jE c^/Z娇Bt=&#@#LCi՜9ar]W偷 !9$5JװLR+l>̇FPkE;RrQWΦv h0Ftz3 t=" zP)WQV>$O[%ا6X'j*3{ q.GI:v˟6UIhە]҄aj$ʸcqV%(##Bʩxv9 ioÓ`] $D4TP. F wts4ӥ"§DcnP=X O  6;e~ΕP Ȁttrֶ.qjZ+f]v)yS,r|ւY匂ivFp`aO5QrH|- 7bHC =>Pau|Mꉌ:՜t+z+wَɴ\r%DD$>SM\*wޥޅ^鸣¸-]v=jOi|HNTUh(H*77]oc;n "GEkńB]AQ Kzəf_/6AȒ̄}}ZڪzNU Xڪx d_ouE63*  D^1n8j PEy&0us\w@&@Pk0j~=~p lh}aa:aadۢuC! 08u;@ugOo]8Nnx2כu<:   y׋↮  S PϯH 4/J(&ʬם~M)ϯO;O,O Y e@ +C{M#_zB%ׇ.Y P=~J/k0 @0:́@m"J@UA׻E\_ t!]BqA@@.9 h& oGu:t   "@%>l[!uT s~}:9+kX~   P8<º9O9/V@@` `~+  0A_`"K  sK>EL@ߺz͞"? RG@@@ tݖj:qzD2d ,ؓ@tF?9!tc԰!A@@`/--Ye\49wBLGڟCfA@@ u HyfOɡtA@@` oo~} y\_1q0{i"!׍Lr3QhZQЇ   @P)-{nݗ@@ZpVm|O4zA@@`>xD|D.A@@Dsn@PUq۬ p7 THmz @@@b`=| %1I2|p/,,4ƆM^+[IENDB`}DyK _Ref516049189}DyK _Ref509291474@D`D xNormalOJQJ_HaJmH sH tH T`T x Heading 1$ & F<@&CJ KH ^JaJ V`V x Heading 2$ & F<@&6CJ]^JaJV`V x Heading 3$ & F<@&5CJ\^JaJD`D x Heading 4$ & F@&>*^JT`T x Heading 5 & F<@&56CJ\]aJN`N x Heading 6 & F<@&5CJ\aJ@`@ x Heading 7 & F<@&F`F x Heading 8 & F<@&6]T `T x Heading 9 & F<@&CJOJQJ^JaJDA`D xDefault Paragraph FontVi V x Table Normal :V 44 la (k (xNo List \oA\xASML& <<-D`M PJ^JmHnHu:`: x Footnote TextaJ@& @ xFootnote ReferenceH*4 `"4 xFooter  !.)`1. x Page Number@Z`B@ x Plain TextOJQJ^JaJRY`RR x Document Map-D M OJ QJ ^J .(`a. x Line Number4`r4 xHeader  !6U@6 Hyperlink >*B*phFV@F FollowedHyperlink >*B* phFoFx ASMLSubDoc-D`M 5H"@H Caption xx5CJOJQJ\aJ0o0 xpicture$a$DoD xCode OJQJ^J_HaJmH sH tH JOJ BulletList$ & Fa$ CJOJQJDOD NumberList  & F CJOJQJ.X@. Emphasis6]0o0 xMathSymbOJQJDo"D x blockquote"xx^6Fo2F x ASM Signature#CJOJQJ^J:o1B: x ASM Macro$ CJOJ QJ 4o1R4 x ASM Rule Def%4B`b4 x Body Text&$a$6P`r6 x Body Text 2'CJ$<o< x Open Issue( CJOJ QJ :o1: x Quotation) CJOJ QJ LQ`L x Body Text 3 *7$8$H$CJOJQJaJ,o, x codeintext@>@@ Title,$<a$ 5CJKHJg`J xHTML TypewriterCJOJQJ^JaJPT@P Block Text.$]^a$ 6]_H 6O6 TRnumber/$a$CJ.L@. Date0$a$CJ:J@: Subtitle 1$<a$CJ2O"2 Author2$a$CJ0O20 Address3d(O( Style14(O!R( Style25&@& TOC 16.@. TOC 2 7^.@. TOC 3 8^.. TOC 4 9X^X.. TOC 5 : ^ .. TOC 6 ;^.. TOC 7 <^.. TOC 8 =x^x.. TOC 9 >@^@JOJ Code Char OJQJ^J_HaJmH sH tH  i       i "ճֳ#B}ø 1[=Ihʻݻ޻K^_+<N_oĽ$()mnۿܿ %1@GHS\fo{ 2\12UVex4BerGf )7|H}Cz$V|#O Ic}-%>Par?c3CVWjSi0?Uey8svc|@Uh~0|BCU^grs9jCm#9Nex:;O>?_z"#3^;u*RyN,Fwx5\]w)PbdqBd?YkI`@s<r~(9`_{45b #(./@x9kGo:b/GHo0_3g # ? d {     $ ? _ ~     . A    2 J m     7 c d w      =fn !P{&Dq9d?m-?n1=JV BWk8Y~ NuPb2`.Z 07Kq}/Oo9Qcw3iz(:BVd $ V v      !!'!k!!!!! ""B"b"""""""##X#r#####$3$S$z$$$$$$$%M%g%%%%%% &.&Q&]&~&&&&&&' '+'?'P''''''''(6(?(^(j(~(((((()+)?)f)))***5*V*]*r*****++++W+a+q+++,,G,u,,,,,,,-=-`-p-------..*.<.i.{....(/A/s//////50S0000000 1/1^1111 22+2K2`2h2n2~22222223!343=3N3O3`3{33334N4s444444455O5P5p555556D6u6v6666677V777777+8^88888989Y9t99999: :):G:g:::::::;;A;\;e;;;;;;<(<-<=<H<e<z<<<<<<</=;=K=q=====>>)>9>J>j>>>>>>?6???^?_?i?y?????@A@L@s@@@@@@AAA1B9BNB]BnBwBBB CC*C_CCCCD=DDD E8EEEZEEEEFIFvFFFGNGGGHCHHHH2IeIIII.J`JJJJJKJKKKKKL9LcLLLL=MkMMM+NpNNNOIOxOOOP@P}PPP QYQQQQ&RWRRRR)S^SSS T>TUTjTTTTTTU)UWUUUU V6V;VPVgVVVVVVW=WBWWW`WWWWWWWX;XeXxXXXXXY'Y\YkYYYYYZZJZ~ZZZZ [[)[[[["\;\U\]\v\\\ ]8]Y]b]]]]]^M^^^^,_U____"`C`````` aGaaaabZbbb c@cIc}cccdEdLddddd#e]eeeeefWffffg#g\gggg,h_hhhh0iZiiiiij+j6jKjjjjj+kUkokkkkkklMl|lll m.mTmsmmmmmmnJnvnnnnn#oRo{ooo ppVpqpppp;qfqqqrrdrrrs>stssstCtqtttuKuuuu>vwvvv!wUwwww(xYxxxx6ywyyy$zbzzzz1{e{y{{{|,|E|f||||},}X}g}o}}}}}*~X~~~~3L|%TuÀ/HUoǁ &KfCM~à .PQwԄل cd,5doÆĆ_dLJ܇*9:È܈Jh#H,-IgȋW#DY{ʍ1rՎ7Xmy OhBv @Mfzђ4PVo֓+Xc"RՕ NV|3U0]ku&jz00 80 +:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:00 80+:00 80+:00 80+:00 80+:00 80+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:00 80+:00!80+:00"80+:00#80+:00$80+:00%80+:00&80+:00'80+:00(80+:00)80+:00*80+:00+80+:00,80+:00-80+:00.80+:00/80+:00080+:00180+:00280+:00380+:00480+:00580+:00680+:00780+:00880+:00980+:00:80+:00;80+:00<80+:00=80+:00>80+:00?80+:00@80+:00A80+:00B80+:00C80+:00D80+:00E80+:00F80+:00G80+:00H80+:00I80+:00J80+:00K80+:00L80+:00M80+:00N80+:00O80+:00P80+:00Q80+:00R80+:00S80+:00T80+:00U80+:00V80+:00W80+:00X80+:00Y80+:00Z80+:00[80+:00\80+:00]80+:00^80+:00_80+:00`80+:00a80+:00b80+:00c80+:00d80+:00e80+:00f80+:00g80+:00h80+:00i80+:00j80+:00k80+:00l80+:00m80+:00n80+:00o80+:00p80+:00q80+:00r80+:00s80+:00t80+:00u80+:00v80+:00w80+:00x80+:00y80+:00z80+:00{80+:00|80+:00}80+:00~80+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:00 80+:00 80+:00 80+:00 80+:00 80+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:00 80+:00!80+:00"80+:00#80+:00$80+:00%80+:00&80+:00'80+:00(80+:00)80+:00*80+:00+80+:00,80+:00-80+:00.80+:00/80+:00080+:00180+:00280+:00380+:00480+:00580+:00680+:00780+:00880+:00980+:00:80+:00;80+:00<80+:00=80+:00>80+:00?80+:00@80+:00A80+:00B80+:00C80+:00D80+:00E80+:00F80+:00G80+:00H80+:00I80+:00J80+:00K80+:00L80+:00M80+:00N80+:00O80+:00P80+:00Q80+:00R80+:00S80+:00T80+:00U80+:00V80+:00W80+:00X80+:00Y80+:00Z80+:00[80+:00\80+:00]80+:00^80+:00_80+:00`80+:00a80+:00b80+:00c80+:00d80+:00e80+:00f80+:00g80+:00h80+:00i80+:00j80+:00k80+:00l80+:00m80+:00n80+:00o80+:00p80+:00q80+:00r80+:00s80+:00t80+:00u80+:00v80+:00w80+:00x80+:00y80+:00z80+:00{80+:00|80+:00}80+:00~80+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080z00 80 +:0080@0|t+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00 ,80,+z00 ,80,+z00 ,80,+z00 ,80,+z00 ,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00 ,80,+z00!,80,+z00",80,+z00#,80,+z00$,80,+z00%,80,+z00&,80,+z00',80,+z00(,80,+z00),80,+z00*,80,+z00+,80,+z00,,80,+z00-,80,+z00.,80,+z00/,80,+z000,80,+z001,80,+z002,80,+z003,80,+z004,80,+z005,80,+z006,80,+z007,80,+z008,80,+z009,80,+z00:,80,+z00;,80,+z00<,80,+z00=,80,+z00>,80,+z00?,80,+z00@,80,+z00A,80,+z00B,80,+z00C,80,+z00D,80,+z00E,80,+z00F,80,+z00G,80,+z00H,80,+z00I,80,+z00J,80,+z00K,80,+z00L,80,+z00M,80,+z00N,80,+z00O,80,+z00P,80,+z00Q,80,+z00R,80,+z00S,80,+z00T,80,+z00U,80,+z00V,80,+z00W,80,+z00X,80,+z00Y,80,+z00Z,80,+z00[,80,+z00\,80,+z00],80,+z00^,80,+z00_,80,+z00`,80,+z00a,80,+z00b,80,+z00c,80,+z00d,80,+z00e,80,+z00f,80,+z00g,80,+z00h,80,+z00i,80,+z00j,80,+z00k,80,+z00l,80,+z00m,80,+z00n,80,+:00m80+:00n80+:00n80+:00o80+:00p80+z00o,80,+z00s,80,+z00t,80,+z00u,80,+z00,80,+:00w80+:00x80+:00y80+:00z80+:00{80+:00|80+:00}80+:00~80+:0080+:0080+:0080+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00 ,80,+z00 ,80,@0|t+z0080+z0080+z0080+z00,80,+z00 ,80,+:00 80+:00 80+:00 80+:00 80+z0080+z00 ,80,+z00 ,80,+z00,80,+z00,80,+z00,80,+:0080+z00,80,+z00,80,+z00,80,+z00,80,+z0080+z0080+z0080+z0080+z0080+z0080+z0080+z0080+z0080+z0080+z0080+z0080+z00"80+:00&80+:00'80+:00(80+:00)80+:00*80+:00+80+:00,80+:00-80+:00.80+:00/80+:00080+:00180+:00280+:00380+z00#80+z00$80+:00680+:00780+z00%80+z00&80+:00:80+:00;80+z00'80+z00(80+z00J,80,+z00K,80,+z00L,80,+z00M,80,+z00*80+z00+80+z00,80+z00-80+z00B,80,+z00.80+:00H80+:00I80+:00&80+:00&80+:00'80+z00/80+z00s,80,+z00t,80,+z00u,80,+z00,80,+:00R80+:00S80+:00T80+:00U80+:00V80+:00W80+:00X80+:00Y80+:00Z80+:00[80+:00\80+z00,80,+:00^80+:00_80+:00`80+:00a80+:00b80+:00c80+:00d80+z00,80,+z00V80+z00V80+z00,80,+z00W80+:00j80+:00k80+:00l80+:00m80+:00n80+:00o80+:00p80+:00q80+:00r80+:00s80+:00t80+:00u80+:00v80+:00w80+:00x80+:00y80+:00z80+:00{80+:00|80+:00}80+:00~80+z00,80,+z00,80,+z00,80,+z00,80,+:0080+z00,80,+:0080+:0080+:0080+z00^80+z00^80+:0080+:0080+:0080+:0080+z00,80,+z00a80+z00b80+z00c80+z00d80+z00e80+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00m80+z00,80,+z00o80+z00p80+z00q80+z00r80+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,+z00,80,@0w+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+:0080+z00|80@0pz00.T 80T +:00Y80+:00Y80z00 80 z00 80 z00 80 z00 80 +:00S 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 +:00[ 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 +:00g 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00! 80 z00" 80 z00# 80 z00$ 80 z00% 80 z00& 80 z00' 80 z00( 80 z00) 80 z00* 80 z00+ 80 z00, 80 z00- 80 z00. 80 z00/ 80 z000 80 z001 80 +:00 80 z002 80 z003 80 z004 80 z005 80 z006 80 z007 80 z008 80 z009 80 z00: 80 z00; 80 z00< 80 z00= 80 z00> 80 z00? 80 z00@ 80 z00A 80 z00B 80 z00C 80 z00D 80 z00E 80 z00F 80 z00G 80 z00H 80 z00I 80 z00J 80 z00K 80 z00L 80 z00M 80 z00N 80 z00O 80 z00P 80 z00Q 80 z00R 80 z00S 80 z00T 80 z00U 80 z00V 80 z00W 80 z00X 80 z00Y 80 z00Z 80 z00[ 80 z00\ 80 z00] 80 z00^ 80 z00_ 80 +:00 80 z00` 80 z00a 80 z00b 80 z00c 80 z00d 80 +:00 80 z00e 80 z00f 80 z00g 80 z00h 80 z00i 80 z00j 80 z00k 80 z00l 80 +:00 80 z00m 80 z00n 80 z00o 80 z00p 80 +:00 80 z00q 80 z00r 80 z00s 80 z00t 80 +:00 80 z00u 80 z00v 80 z00w 80 z00 80 +:00 80 +:00 80 +:00 80 +:00 80 +:00 80 +:00 80 z00 80 z00 80 z00 80 z00 80 z00x 80 z00{ 80 +:00 80 +:00 80 z00| 80 +z00}\80\+z00~\80\+z00\80\z00 80 z00 80 +z00\80\+z00\80\+z00\80\z00 80 z00 80 +z00\80\+z00\80\z00 80 +z00\80\z00 80 +z00\80\+z00\80\z00 80 z00 80 z00 80 z00 80 +z00\80\z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 +z00\80\z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 +z00\80\z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 @0wz00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00  80 z00  80 z00  80 z00  80 z00  80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00  80 z00! 80 z00" 80 +z00\80\z00# 80 z00$ 80 z00% 80 z00& 80 z00' 80 z00( 80 z00) 80 z00* 80 z00+ 80 z00, 80 z00- 80 z00. 80 z00/ 80 z000 80 z001 80 z002 80 z003 80 z004 80 z005 80 z006 80 z007 80 z008 80 z009 80 z00: 80 z00; 80 z00< 80 z00= 80 z00> 80 z00? 80 z00@ 80 z00A 80 z00B 80 z00C 80 z00D 80 z00E 80 z00F 80 z00G 80 z00H 80 z00I 80 z00J 80 z00K 80 z00L 80 z00M 80 z00N 80 z00O 80 z00P 80 z00Q 80 z00R 80 z00S 80 z00T 80 z00U 80 z00V 80 z00W 80 z00X 80 z00Y 80 z00Z 80 z00[ 80 z00\ 80 z00] 80 z00^ 80 z00_ 80 z00` 80 z00a 80 z00b 80 z00c 80 z00d 80 z00e 80 z00f 80 z00g 80 z00h 80 z00i 80 z00j 80 z00k 80 z00l 80 z00m 80 z00n 80 z00o 80 z00p 80 z00q 80 z00s 80 z00p0800z00q0800z00r0800z00s0800z00t 80 z00u 80 +z00G\80\+z00H\80\z00v 80 z00w 80 z00x 80 z00y 80 z00z 80 z00{ 80 z00| 80 z00} 80 +z00Q\80\z00~ 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 +z00i\80\z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 +z00q\80\z00 80 z00 80 z00 80 z00 80 +z00v\80\z00 80 +z00}80z00 80 +z00y\80\z00 80 +z0080z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 +z00\80\z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 +z00\80\z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 +z00\80\+z00\80\+z00\80\+z00\80\+z0080+z00\80\+z00\80\+z0080+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z0080+z00\80\+z0080+z0080+z0080+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z0080+z0080+z00\80\+z0080+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\+z00\80\z00 80 +z00\80\+z0080+z00\80\+z00\80\+z0080+z0080+z0080+z0080+z0080+z0080+z00\80\z00 80 +z00\80\z00 80 z00 80 z00 80 +z00\80\+z00\80\z00 80 z00 80 +z00\80\+z00D80D+z00D80D+z00D80D+z00\80\+z00\80\z00 80 +z0080z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 z00 80 @0w+:00m 80 +:00o 80 +:00o 80 +:00p 80 +:00q 80 +:00r 80 +:00s 80 +:00t 80  0Q+:00v 80 +:00w 80 +:00x 80 #:00y 80 ()*P{| )IZ}< W # 1 M c /-<A?=0 ce 9$;$&&++ -- -S/d/11124344c55#66 7}77899999999999-:2:8:=::::::::::;;;;;;;; ; ; ; ; ;;;;;;;;;A;B;_;P==J>P@j@#E$E%E'E(E)E*E+E,E-E.E/E0E1E2E3E4E5EzE{EH7HJJJJoKKMM;NN5O{PQ5RRR`TwTxT UU,U-UUUUV-V.VVVVgWWWWKXhX[[[[[^^^____+b,b?b@bbb c?c@cpeeeeeeeee f>g[g\ghhhCjjjj(k)k\kk5lLln noooop q)qDqSrrrrrrssstt8tu v vwwwx$y?yYyiyyyyyy||~~01 !%3PQIT$&WX8i֐3bo+,hœ#/0+|ɖ7yzɘܘETKL\$@efmOˣ5[z4W~|}HIXj|}Ѩ;[-MN`Ƭ @t]^ "ճֳ#B}ø 1[=Ihʻݻ޻K^_+<N_oĽ$()mnۿܿ %1@GHS\fo{ 2\12UVex4BerGf )7|H}Cz$V|#O Ic}-%>Par?c3CVWjSi0?Uey8svc|@Uh~0|BCU^grs9jCm#9Nex:;O>?_z"#3^;u*RyN,Fwx5\]w)PbdqBd?YkI`@s<r~(9`_{45b #(./@xmn*5t#&Z9kGo:b/GHo0_3g # ? d {     $ ? _ ~     . A    2 J m     7 c d w      =fn !P{&Dq9d?m-?n1=JV BWk8Y~ NuPb2`.Z 07Kq}/Oo9Qcw3iz(:BVd $ V v      !!'!k!!!!! ""B"b"""""""##X#r#####$3$S$z$$$$$$$%M%g%%%%%% &.&Q&]&~&&&&&&' '+'?'P''''''''(6(?(^(j(~(((((()+)?)f)))***5*V*]*r*****++++W+a+q+++,,G,u,,,,,,,-=-`-p-------..*.<.i.{....(/A/s//////50S0000000 1/1^1111 22+2K2`2h2n2~22222223!343=3N3O3`3{33334N4s444444455O5P5p555556D6u6v6666677V777777+8^88888989Y9t99999: :):G:g:::::::;;A;\;e;;;;;;<(<-<=<H<e<z<<<<<<</=;=K=q=====>>)>9>J>j>>>>>>?6???^?_?i?y?????@A@L@s@@@@@@AAA1B9BNB]BnBwBBB CC*C_CCCCD=DDD E8EEEZEEEEFIFvFFFGNGGGHCHHHH2IeIIII.J`JJJJJKJKKKKKL9LcLLLL=MkMMM+NpNNNOIOxOOOP@P}PPP QYQQQQ&RWRRRR)S^SSS T>TUTjTTTTTTU)UWUUUU V6V;VPVgVVVVVVW=WBWWW`WWWWWWWX;XeXxXXXXXY'Y\YkYYYYYZZJZ~ZZZZ [[)[[[["\;\U\]\v\\\ ]8]Y]b]]]]]^M^^^^,_U____"`C`````` aGaaaabZbbb c@cIc}cccdEdLddddd#e]eeeeefWffffg#g\gggg,h_hhhh0iZiiiiij+j6jKjjjjj+kUkokkkkkklMl|lll m.mTmsmmmmmmnJnvnnnnn#oRo{ooo ppVpqpppp;qfqqqrrdrrrs>stssstCtqtttuKuuuu>vwvvv!wUwwww(xYxxxx6ywyyy$zbzzzz1{e{y{{{|,|E|f||||},}X}g}o}}}}}*~X~~~~3L|%TuÀ/HUoǁ &KfCM~à .PQwԄل cd,5doÆĆ_dLJ܇*9:È܈Jh#H,-IgȋW#DY{ʍ1rՎ7Xmy OhBv @Mfzђ4PVo֓+Xc"RՕ NV|3U0]ku&'GWXZj0000000000000000000000000000000606070706070808080808070808080708080806070707080808070808070808080708080808080808060606060600 000000"00000000000 00- 0--0S/0S/0S/ 0S/ 0S/ 0S/0S/0S/ 0S/ 0S/ 0S/ 0S/ 0S/ 0S/ 0--07 0 7 0 7 0 7 0 7 0 7 07 07 07 070707 07 07 07 07 07 07 0707%070707070707070707070707070707070707070707070707070707 00B;/ 0B;/ 0B;0B; 0B;B;0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@( 0P@P@0H0H0H0H0H0H0H0H0H- 0H- 0H- 0H- 0H- 0H- 0H( 0P@P@0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R( 0P@P@0KX0KX0KX0KX0KX0KX0KX( 0P@P@0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^( 0P@P@0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e 0B;B;05l( 05l5l0n0n0n0n0n0n0n( 05l5l0)q0)q0)q0)q0)q0)q0)q0)q0)q0)q( 05l5l0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t 0B;B;0|( 0||0~0~0~0~0~0~0~0~0~( 0||0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%0%&0%0%0%0%0%0%0%0%0%0%( 0||0001 01 01 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00^0^0^ 0^^0 0 0 0 0 0 0 0 0 0 0 0 0 0  0^^0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0}0} 0^^00( 00+0+0+0+0+0+0+0+0+8 0++00000000( 000000000000000000000000000000000000000000( 0008 00008 00e0e0e0e0e0e0e0e0e 0^^0)0)0)0)0)0)0)( 0))00000000000000000000000000( 0))0}0}0} 0^^0000000000000000000000000000000( 00000000( 000000000000000000000000000000000000000( 00|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0| 0^^0000000000000000000000000000000( 0000000000000000000008 00^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^8 0000000000000000000000000000( 00000000000000000000000000000000( 00r0r( 000( 000( 000000000000000000000000( 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  000000000. 0*. 0*. 0*. 0*. 0*. 0*. 0*. 0*. 0*. 0 *. 0 *. 0 *. 0 *. 0 *. 0*0* 000000000000000000000000000000000000000 00# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0# 0#  00d 0d ( 0d d 8 0  0 0 0 0 8 0  0f0f8 0  008 0  000( 0d d 8 0{{0008 0{{000000000008 0{{0000000008 0{{000000000000000000008 0{{0B0B0B0B0B0B8 0{{00000000000000000000000000000008 0{{0000( 0d d 8 0008 0000000000000000000000000000000000000000000( 0d d 8 0990Q0Q0Q0Q0Q0Q0Q0Q0Q8 0990i0i0i0i0i0i0i8 0990:0:0:0:0:0:0:0:0:0:0:0:0:0:8 0990 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0990"0"0"0"0"0"0"0"0"0"0"0"0"0"0"0"8 0990$0$0$0$0$0$0$0$0$0$0$0$0$0$8 0990~&0~&0~&0~&0~&0~&8 0990 '0 '0 '0 '0 '0 '8 0990'0'0'0'0'0'8 0 990^(0^(0^(8 0 990(0(0(8 0 990)0)0)0)0)0) 00*0*( 0**8 0V*V*0]*0]*0]*0]*0]*8 0V*V*0+0+8 0V*V*0W+0W+0W+8 0V*V*0+0+0+( 0**0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,0u,8 0u,u,0 20 20 2( 0**8 0`2`20h20h28 0`2`2020202020202020202020202020202020202020202( 0**8 044040404040404040404040404040404040404040404048 04407070707070707070707070707078 0440909090909090909090909098 0440:0:0:0:0:0:0:0:0:0:0:0:8 0440(<0(<0(<0(<0(<0(<0(<0(<8 0440<0<8 0440/=0/=0/=0/=0/=0/=0/=0/=8 0440>0>0>0>0>0>0>0>0>0>0>0>0>8 0440_?0_?0_?0_?0_?0_?0_?0_?0_?0_?0_?0_?0_? 00@ 0@@0A0A( 0AA01B01B01B01B01B01B01B( 0AA0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C( 0AA08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E08E( 0AA0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J0J( 0AA0>T0>T0>T0>T0>T( 0AA0T0T0T0T0T0T0T0T( 0AA06V06V06V06V( 0AA0V0V0V0V( 0AA0=W0=W0=W0=W0=W0=W( 0 AA0W0W0W0W( 0 AA0eX0eX0eX0eX0eX 0@@0Y( 0YY0\Y0\Y0\Y0\Y( 0YY0Y0Y0Y0Y0Y0Y0Y0Y( 0YY0[0[0[0[0[0[( 0YY0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\0U\( 0YY0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`0`( 0YY0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k0k( 0YY0|0|0|0|0|0|0|0|0|( 0YY0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}0g}( 0YY0000000( 0 YY000000000000000000000( 0 YY0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ0Ԅ( 0 YY0_0_0_0_0_0_0_0_( 0 YY0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*8 0**0-0-0-0-0-0-0-0-0-0-0-0-0-8 0**0Y0Y0Y0Y0Y0Y0Y0Y0Y0Y0Y0Y8 0**0m0m0m8 0**0O0O0O0O0O0O0O0O0O0O0O( 0 YY0@0@0@0@0@0@0@0@0@( 0YY0P0P0P0P0P0P 0@@( 0++0X0X0X( 0++000( 0++000( 0++0N0N( 0++0000 0@@( 0000000( 00000My00h@0@0p0 M90()*P{| )IZ}< W # 1 M c /-<A?=0 ce 9$;$&&++ -- -S/d/11124344c55#66 7}77899999999999-:2:8:=::::::::::;;;;;;;; ; ; ; ; ;;;;;;;;;A;B;_;P==J>P@j@#E$E%E'E(E)E*E+E,E-E.E/E0E1E2E3E4E5EzE{EH7HJJJJoKKMM;NN5O{PQ5RRR`TwTxT UU,U-UUUUV-V.VVVVgWWWWKXhX[[[[[^^^____+b,b?b@bbb c?c@cpeeeeeeeee f>g[g\ghhhCjjjj(k)k\kk5lLln noooop q)qDqSrrrrrrssstt8tu v vwwwx$y?yYyiyyyyyy||~~01 !%3PQIT$&WX8i֐3bo+,hœ#/0+|ɖ7yzɘܘETKL\$@efmOˣ5[z4W~|}HIXj|}Ѩ;[-MN`Ƭ @t]^ "ճֳ#B}ø 1[=Ihʻݻ޻K^_+<N_oĽ$()mnۿܿ %1@GHS\fo{ 2\12UVex4BerGf )7|H}Cz$V|#O Ic}-%>Par?c3CVWjSi0?Uey8svc|@Uh~0|BCU^grs9jCm#9Nex:;O>?_z"#3^;u*RyN,Fwx5\]w)PbdqBd?YkI`@s<r~(9`_{45b #(./@xn*5t#&Z9kGo:b/GHo0_3g # ? d {     $ ? _ ~     . A    2 J m     7 c d w      =fn !P{&Dq9d?m-?n1=JV BWk8Y~ NuPb2`.Z 07Kq}/Oo9Qcw3iz(:BVd $ V v      !!'!k!!!!! ""B"b"""""""##X#r#####$3$S$z$$$$$$$%M%g%%%%%% &.&Q&]&~&&&&&&' '+'?'P''''''''(6(?(^(j(~(((((()+)?)f)))***5*V*]*r*****++++W+a+q+++,,G,u,,,,,,,-=-`-p-------..*.<.i.{....(/A/s//////50S0000000 1/1^1111 22+2K2`2h2n2~22222223!343=3N3O3`3{33334N4s444444455O5P5p555556D6u6v6666677V777777+8^88888989Y9t99999: :):G:g:::::::;;A;\;e;;;;;;<(<-<=<H<e<z<<<<<<</=;=K=q=====>>)>9>J>j>>>>>>?6???^?_?i?y?????@A@L@s@@@@@@AAA1B9BNB]BnBwBBB CC*C_CCCCD=DDD E8EEEZEEEEFIFvFFFGNGGGHCHHHH2IeIIII.J`JJJJJKJKKKKKL9LcLLLL=MkMMM+NpNNNOIOxOOOP@P}PPP QYQQQQ&RWRRRR)S^SSS T>TUTjTTTTTTU)UWUUUU V6V;VPVgVVVVVVW=WBWWW`WWWWWWWX;XeXxXXXXXY'Y\YkYYYYYZZJZ~ZZZZ [[)[[[["\;\U\]\v\\\ ]8]Y]b]]]]]^M^^^^,_U____"`C`````` aGaaaabZbbb c@cIc}cccdEdLddddd#e]eeeeefWffffg#g\gggg,h_hhhh0iZiiiiij+j6jKjjjjj+kUkokkkkkklMl|lll m.mTmsmmmmmmnJnvnnnnn#oRo{ooo ppVpqpppp;qfqqqrrdrrrs>stssstCtqtttuKuuuu>vwvvv!wUwwww(xYxxxx6ywyyy$zbzzzz1{e{y{{{|,|E|f||||},}X}g}o}}}}}*~X~~~~3L|%TuÀ/HUoǁ &KfCM~à .PQwԄل cd,5doÆĆ_dLJ܇*9:È܈Jh#H,-IgȋW#DY{ʍ1rՎ7Xmy OhBv @Mfzђ4PVo֓+Xc"RՕ NV|3U0]ku&j0000000000000000000000000000000606070706070808080808070808080708080806070707080808070808070808080708080808080808060606060600  000000"00000000000  00- 0--0S/0S/0S/ 0S/ 0S/ 0S/0S/0S/ 0S/ 0S/ 0S/ 0S/ 0S/ 0S/ 0--07 0 7 0 7 0 7 0 7 0 7 07 07 07 070707 07 07 07 07 07 07 0707%070707070707070707070707070707070707070707070707070707  00B;/ 0B;/ 0B;0B; 0B;B;0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@0P@* 0P@P@0;H0;H0;H0;H0;H0;H0;H0;H0;H- 0;H- 0;H- 0;H- 0;H- 0;H- 0;H* 0P@P@0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R0R* 0P@P@0iX0iX0iX0iX0iX0iX0iX* 0P@P@0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^0^* 0P@P@0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 0B;B;0Sl* 0SlSl0n0n0n0n0n0n0n* 0SlSl0Gq0Gq0Gq0Gq0Gq0Gq0Gq0Gq0Gq0Gq* 0SlSl06t06t06t06t06t06t06t06t06t06t06t06t06t06t06t06t 0B;B;0|* 0||0P~0P~0P~0P~0P~0P~0P~0P~0P~* 0||0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t&0t0t0t0t0t0t0t0t0t0t* 0||0e0e0e1 0e1 0e1 0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e  0000 00Y0Y0Y0Y0Y0Y0Y0Y0Y0Y0Y0Y0Y0Y 00̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸0̸ 000* 00z0z0z0z0z0z0z0z0z: 0zz0Q0Q0Q0Q0Q0Q0Q0Q* 000000000000000000000000000000000000000000* 000: 00%0%0%: 0000000000 00x0x0x0x0x0x0x* 0xx00000000000000000000000000* 0xx000 00h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h0h* 0hh0000000* 0hh0000000000000000000* 0hh00000000000000000 00a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a* 0aa00000000000000000000: 000000000000000000000000000000000: 0040404040404040404040404040404040404040404040404040404* 0aa0000000000000000000000000000000* 0aa00* 0aa00* 0aa0/0/* 0aa0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_* 0aa0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[0[  00B0B0B0B 00 0. 0&. 0&. 0&. 0&. 0&. 0&. 0&. 0&. 0&. 0 &. 0 &. 0 &. 0 &. 0 &. 0&0&  000000000000000000000000000000000000000 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  00`0`* 0``: 00000: 00b0b: 000: 0000* 0``: 0ww000: 0ww00000000000: 0ww000000000: 0ww00000000000000000000: 0ww0>0>0>0>0>0>: 0ww0000000000000000000000000000000: 0ww0000* 0``: 000: 00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,* 0``: 0550M0M0M0M0M0M0M0M0M: 0550e0e0e0e0e0e0e: 05506 06 06 06 06 06 06 06 06 06 06 06 06 06 : 0550!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!: 0550#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#: 0550%0%0%0%0%0%0%0%0%0%0%0%0%0%: 0550z'0z'0z'0z'0z'0z': 0550(0(0(0(0(0(: 0550(0(0(0(0(0(: 0 550Z)0Z)0Z): 0 550)0)0): 0 550*0*0*0*0*0* 00*0** 0**: 0R+R+0Y+0Y+0Y+0Y+0Y+: 0R+R+0,0,: 0R+R+0S,0S,0S,: 0R+R+0,0,0,* 0**0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-0q-: 0q-q-030303* 0**: 0\3\30d30d3: 0\3\3030303030303030303030303030303030303030303* 0**: 05505050505050505050505050505050505050505050505: 0550808080808080808080808080808: 0550:0:0:0:0:0:0:0:0:0:0:0:: 0550;0;0;0;0;0;0;0;0;0;0;0;: 0550$=0$=0$=0$=0$=0$=0$=0$=: 0550=0=: 0550+>0+>0+>0+>0+>0+>0+>0+>: 0550?0?0?0?0?0?0?0?0?0?0?0?0?: 0550[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@0[@  00A 0AA0B0B* 0BB0-C0-C0-C0-C0-C0-C0-C* 0BB0 D0 D0 D0 D0 D0 D0 D0 D0 D0 D0 D* 0BB04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F04F* 0BB0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K* 0BB0:U0:U0:U0:U0:U* 0BB0U0U0U0U0U0U0U0U* 0BB02W02W02W02W* 0BB0W0W0W0W* 0BB09X09X09X09X09X09X* 0 BB0X0X0X0X* 0 BB0aY0aY0aY0aY0aY 0AA0 Z* 0 Z Z0XZ0XZ0XZ0XZ* 0 Z Z0Z0Z0Z0Z0Z0Z0Z0Z* 0 Z Z0\0\0\0\0\0\* 0 Z Z0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]0Q]* 0 Z Z0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a* 0 Z Z0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l0l* 0 Z Z0}0}0}0}0}0}0}0}0}* 0 Z Z0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~0c~* 0 Z Z0 0 0 0 0 0 0 * 0 Z Z000000000000000000000* 0 Z Z0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ0Ѕ* 0 Z Z0[0[0[0[0[0[0[0[* 0 Z Z0&0&0&0&0&0&0&0&0&0&0&0&0&0&0&0&: 0&&0)0)0)0)0)0)0)0)0)0)0)0)0): 0&&0U0U0U0U0U0U0U0U0U0U0U0U: 0&&0i0i0i: 0&&0K0K0K0K0K0K0K0K0K0K0K* 0 Z Z0<0<0<0<0<0<0<0<0<* 0 Z Z0L0L0L0L0L0L 0AA* 0''0T0T0T* 0''000* 0''000* 0''0J0J* 0''0000 0AA* 0000000* 00000 2225 C y\#{GN>_)8Q#.29COXfjmorxRڬy/7 N9 &*/{3:]@uE JOTzZ_ocMjsyX i   "%(+.0369;>ACFILOQSUWZ\^acfilp) 4;BC/M5WK`ms|XѰ][+%x}3^wY 9  !#('b*-60259<?B;EGKeQVU\_b,gLlZqsuz(goǏXkBi   !#$&')*,-/124578:<=?@BDEGHJKMNPRTVXY[]_`bdeghjkmnoqrh(DFGIi9UWXZz<\xz{}79:<\   $ 5 Q T U W w   ! # C ` |   + . / 1 Q e  + G J K M m    ) A ] ` a c ),-/Ob~ '*+-Mf69:<\w ;>?Aar 9<=?_o7:;=]l*-.0Pw8:>Y\4OR57Qln57&&&M'h'j''''m(((((()6)8)***v*******++B+m+o++++x,,,---111*8U8W8k<<<?@@@J@L@zDDDFFFGHHZPuPwP)XDXGXXYY```=aXa^aipppzzz}}}ہ?AƙYKfi6QSi' X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%̕ttttttttttttttttttt #*,5!!23_2$Sﺜ|q;Wufg=-2$׉kקp{2$h^= ` 2$^j' 7hzD#2$jhgxI=ky<@2(    A ?ÔyK FPictures/CHANGE~1.GIF4.Pictures/ChangeDisc.gifZ< / # A%< 0 # AB S  ?;%E[i|t":t/=it0*" 4 _Ref509913490 _Ref509221139 _Toc516654269 _Toc517177085 _Ref509911858 _Ref509912065 _Ref513621725 _Ref510582271 _Ref516021994 _Toc516654270 _Toc517177086 _Ref516463488 _Toc516654271 _Toc517177087 _Ref512138262 _Ref516053232 _Toc516654272 _Toc517177088 _Ref513632444 _Ref516565833 _Toc516654273 _Toc517177089 _Ref513346193 _Ref515953682 _Ref510511786 _Toc516654274 _Toc517177090 _Toc516654275 _Toc517177091 _Toc517177092 _Toc516654276 _Toc517177093 _Hlt513346738 _Hlt513364706 _Toc516654277 _Toc517177094 _Hlt513366454 _Toc516654278 _Toc517177095 _Ref509913282 _Ref511019085 _Toc516654284 _Hlt511019312 _Ref513633309 _Toc517177096 _Toc517177097 _Toc517177098 _Toc517177099 _Toc517177100 _Toc517177101 _Toc517177102 _Hlt513364701 _Ref513364892 _Hlt515954403 _Toc516654287 _Toc517177103 _Ref516565819 _Toc516654288 _Toc517177104 _Toc516654289 _Toc517177105 _Ref517204509 _Toc516654290 _Toc517177106 _Ref511019672 _Toc516654291 _Toc517177107 _Toc516654292 _Toc517177108 _Toc516654293 _Toc517177109 _Toc516654294 _Toc517177110 _Ref511019765 _Toc516654295 _Toc517177111 _Toc516654296 _Toc517177112 _Toc516654297 _Toc517177113 _Ref511019849 _Ref513542702 _Toc516654298 _Toc517177114 _Toc516654299 _Toc517177115 _Toc516654300 _Toc517177116 _Toc516654301 _Toc517177117 _Ref511019816 _Toc516654302 _Toc517177118 _Toc516654303 _Toc517177119 _Toc516654304 _Toc517177120 _Toc516654305 _Toc517177121 _Toc516654306 _Toc517177122 _Toc516654307 _Toc517177123 _Toc516654308 _Toc517177124 _Toc516654309 _Toc517177125 _Hlt509913649 _Ref509913781 _Ref510582540 _Toc516654310 _Toc517177126 _Toc516654311 _Toc517177127 _Toc516654312 _Toc517177128 _Ref509291474 _Ref509291486 _Ref515900839 _Ref509221367 _Hlt509221419 _Ref509992898 _Hlt509992926 _Ref510581274 _Ref513622890 _Hlt509724140 _Hlt509724141 _Ref510239397 _Ref509221591 _Ref509221210 _Ref511556901 _Hlt513366458 _Hlt509910025 _Hlt509910026 _Hlt509910064 _Hlt509910065 _Ref509910336 _Hlt509910038 _Hlt509910039 _Ref515900017 _Ref515900185 _Ref515901015 _Hlt515945487 _Ref515906955 _Ref516049189 _Ref517004973 _Toc516654313 _Toc517177129 _Toc517177130 _Toc517177131 _Toc517177132 _Toc504051338 _Toc504051339 _Toc504051340 _Toc517177133 _Toc504051337 _Toc517177134 _Toc504051354 _Toc517177135 _Toc504051355 _Toc504051356 _Toc504051357 _Toc504051358 _Toc504051359 _Toc504051360 _Toc504051361 _Toc504051362 _Toc504051363 _Toc504051364 _Toc504051365 _Toc517177136 _Toc517177137 _Toc517177138 _Toc517177139 _Toc517177140 _Toc517177141 _Toc517177142 _Toc517177143 _Toc517177144 _Toc517177145 _Toc517177146 _Toc517177147 _Toc517177148 _Toc517177149 _Toc517177150 _Toc517177151 _Toc517177152 _Toc517177153 _Toc517177154 _Toc517177155 _Toc517177156 _Toc517177157 _Toc517177158 _Toc517177159 _Toc517177160 _Toc517177161 _Toc517177162 _Toc517177163 _Toc517177164 OLE_LINK1 _Hlt508600943 _Toc517177165 _Toc517177166 _Toc517177167 _Toc517177168 _Toc517177169 _Toc517177170 _Toc517177171 _Toc517177172 _Toc517177173 _Toc517177174 _Toc517177175 _Toc517177176 _Toc517177177 _Toc517177178 -------S/S/S/d/777B;B;B;B;_;_;P@P@P@HHRKXKX[[^^`ee f f f5l5l5ln)qt|~%^^^ }}++)))}}00||rr **5t#&&&&&Z# d   f{B99Qi: "$~& ''^((*V*u,`24@A1B C8EJ>TT6VV=WWeXY\YY[U\`k|g}Ԅ_*@P+XNj #$@@ !"@%&7-.'@()*+,/012@43@5689:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijk@lmnopqrstuyv@|w@x}z@{@~@@@@@@@@@    -----c/c/c/8888^;^;^;^;^;^;i@i@i@6H6HRgXgX[[^^`e f f f5lKlKl nCq6t|||~2"""^!!!;;666,,,,>>}}44s"%Y= v   mPPbyA!"$&)''i((*[*,g24@A8BCDEJTTT:VVAWWwX&YjYZ([\\`k+|n}؄c8LUWbUj-4QY[cz~ ;<>BCE z~>]^`bcm4STVZ[^89;>?CQopqstw 8:<=BJ&N&&&&&&&M'k'l'n'o'x'''''''m(((((((((((()9):)<)=)F)i)m)))* *!*#*'*v***************+++(+)+,+B+p+r+z+{+|++++++,i,m,x,,,,,,,----.111177*8X8Y8[8]8^8a8888888999999999999999999: :=:K:::::::::;);E<I<k<<<<<<?@@M@N@P@[@\@e@zDDDDDDDFFFFF'G+GGHHH'H(H+HKKZPxPyP{PPPPXX)XHXIXKXQXRXYXXYYY Y YY```````=a_a`abaeafalabbRdVd'e3ere~egghhiiXjbj)k1k2k5kl l"o,oippppppp qqrrrrssssyyDyHy^ybyAzKzzzzzzz{{{i}m}}}}}~~ ~~$24=BL"$.̀ ہ BCEGHLwIUՈT`Ɍ׌'5Əɏُ!"%>DqÐȐ̐͐А,/?VW`|ɑ,CDd“ٓۓޓ|.4zȘۘ͘ƙENclq"0LYoy}˟џDYoY(:Ykȣ-1;NapquƤؤݤ:BCU]qpt,IUZil{}ʨըݨި+,9OUaxy-2N]êɪߪ /959FLMPծٮrv dz˳ah}?F+/ļOT #' txKjknqry6TUW[\fZ4:?F{BV:A !""$$~&& ')'''^(i(((u,, 22h2m2<</=:=>(>_?h?@@A A?ANAAAAAYY\YjYYZ[([[[YeXbNU'JTYZgjQY ;>S>]4S8Qo _8:&&&&&M'k'''m(((()9)* *v*****+B+p+++++,,x,,, ----f11111133448*8X8[8:::;@;;k<<<==??@@M@O@rDzDDDFFFFGGHHJJoKxKOZPxPzPdTgT UUU!UoUqUUUUU#V%VVVWWgWiWWWW)XHXJXhXXYY___` ````5a=a_aba,b2bbbddre~e>gDghhiiCjIjjj)k2kkkoooooippppp qqSrYrrrxrrrssssssttuu vvwwww1x3xyy&y5yDyIy^ycynysy~yyyyyykzzzz7}}}~1F!()ہ ȃBEQfIWTb&7Ɍ،&ŏ>Dqސ ?Wjny{ɑ,DjpɓΓ0>XY|\^ƙEOY^!^`*2DZfkUYҡOXͣӣ';Oaq:C]r~}.ըި,?Aay-4bhƬɬDJ!(gwgzKjn6TzZ"    {XXA[G[__&`B`$Xt€*J2OӄdOgPU;L'JTYZgj33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333| )(GI9XZ\{}:<  5 U W  ! # `  / 1 e + K M  A a c -/b +-f:<w?Ar=?o;=l.0w  ;=S>]_`4SUV8Qo_89&&&A'B'M'k'''''h(j(m(((((()))9)))* *"*#*v*****+++B+p+q+r++++,x,,,- ----S/d/f111178*8X8Z899-:=:::B;_;;k<<<??@@M@O@P@j@rDzDDDFFFFGGHHH7HOZPxPzPRRW)XHXJXKXhXXYY^^ ````5a=a_aaae f5lLln noippp)qDqt8tkzzzz||7}}}~~~)ہ %3ȃBD#ƙUYѡ^ "}+Ľ$ner)7C}-kO^;`r`Kjl6Ty*5atw&    f!{BKid '!"#$%(&& 'P''((()?)**+,u,<.124477e99:;;</=q=>>_??@@AA1BwB C*C8EZEJK>TU6VV=W`WWXeXXXYYZ[)[?\v\` akl||]}}ǁ _d*:-1ryOv@XcNVm!&'HJTWYZj Uwe Glaesser Uwe Glaesser Uwe Glaesser Uwe Glaesser Uwe Glaesser Uwe Glaesser Uwe Glaesser Uwe Glaesser Uwe Glaessermargus1Xn`m ֲnJ4 I)v}Nr*h "3ڑDa}MA &0$6ͤ?(%(I7%<&C- )-31ƊW85(Sz6(&PW-s6Jo(8zj":P\TS[;(r? y1FprSF4Go"EZIBU\Pz+mPXafP/QԐRUrr':V}M|WDX]W ,)ZxuUwnZz Hvh]rEހ%^zX>b^DAeмce}M1|h!;k@u*{]]m^>mZRas%  [sʏ]gxL{-x4|(7b[dh ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`hH.h ^`hH.h pLp^p`LhH.h @ @ ^@ `hH.h ^`hH.h L^`LhH.h ^`hH.h ^`hH.h PLP^P`LhH.h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h^`.h^`.hpLp^p`L.h@ @ ^@ `.h^`.hL^`L.h^`.h^`.hPLP^P`L.h ^`hH.h ^`hH.h pLp^p`LhH.h @ @ ^@ `hH.h ^`hH.h L^`LhH.h ^`hH.h ^`hH.h PLP^P`LhH.h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(^`OJPJQJ^Jo( ^`OJQJo(o pp^p`OJ QJ o( @ @ ^@ `OJQJo( ^`OJQJo(o ^`OJ QJ o( ^`OJQJo( ^`OJQJo(o PP^P`OJ QJ o(h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJ QJ o(h pp^p`OJQJo(oh @ @ ^@ `OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h PP^P`OJQJo(oh   ^ `OJ QJ o(h ^`OJ QJ o(h ^`o(hH.h pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(8  ^ `OJQJo(hH8   ^ `OJQJo(o8   ^ `OJ QJ o(8 xx^x`OJQJo(8 HH^H`OJQJo(o8 ^`OJ QJ o(8 ^`OJQJo(8 ^`OJQJo(o8 ^`OJ QJ o(h ^`OJ QJ o(h^`OJQJo(hHh pp^p`o(hH.h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(hh^h`o(^`.pLp^p`L.h@ @ ^@ `.^`.L^`L.^`.^`.PLP^P`L.h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(hh^h`.P^`P..^`...x^`x....  ^` .....  X@ ^ `X ......  ^ `....... 8x^`8........ `H^``.........h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJ QJ o(h ^`OJ QJ o(hpp^p`OJ QJ o(hHh@ @ ^@ `OJQJo(hHh^`OJQJ^Jo(hHoh^`OJ QJ o(hHh^`OJQJo(hHh^`OJQJ^Jo(hHohPP^P`OJ QJ o(hHh^`.h^`.hpLp^p`L.h@ @ ^@ `.h^`.hL^`L.h^`.h^`.hPLP^P`L.h ^`hH.h ^`hH.h pLp^p`LhH.h @ @ ^@ `hH.h ^`hH.h L^`LhH.h ^`hH.h ^`hH.h PLP^P`LhH.h ^`OJ QJ o(h^`OJQJo(hHh pp^p`o(hH.h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(^`OJPJQJ^J o( ^`OJQJo(o pp^p`OJ QJ o( @ @ ^@ `OJQJo( ^`OJQJo(o ^`OJ QJ o( ^`OJQJo( ^`OJQJo(o PP^P`OJ QJ o(h^`.h^`.hpLp^p`L.h@ @ ^@ `.h^`.hL^`L.h^`.h^`.hPLP^P`L.h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(^`OJPJQJ^Jo( ^`OJQJo(o pp^p`OJ QJ o( @ @ ^@ `OJQJo( ^`OJQJo(o ^`OJ QJ o( ^`OJQJo( ^`OJQJo(o PP^P`OJ QJ o(h ^`hH.h ^`hH.h pLp^p`LhH.h @ @ ^@ `hH.h ^`hH.h L^`LhH.h ^`hH.h ^`hH.h PLP^P`LhH.h^`OJQJo(hHh^`OJQJ^Jo(hHohpp^p`OJ QJ o(hHh@ @ ^@ `OJQJo(hHh^`OJQJ^Jo(hHoh^`OJ QJ o(hHh^`OJQJo(hHh^`OJQJ^Jo(hHohPP^P`OJ QJ o(hHh ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h^`OJQJo(hHh ^`hH.h pLp^p`LhH.h @ @ ^@ `hH.h ^`hH.h L^`LhH.h ^`hH.h ^`hH.h PLP^P`LhH.h^`.^`o(.hpLp^p`L.h@ @ ^@ `.h^`.hL^`L.h^`.h^`.hPLP^P`L.h ^`hH.h ^`hH.h pLp^p`LhH.h @ @ ^@ `hH.h ^`hH.h L^`LhH.h ^`hH.h ^`hH.h PLP^P`LhH.h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h ^`hH.h ^`hH.h pLp^p`LhH.h @ @ ^@ `hH.h ^`hH.h L^`LhH.h ^`hH.h ^`hH.h PLP^P`LhH.h ^`o(hH.h^`OJQJ^Jo(hHohpp^p`OJ QJ o(hHh@ @ ^@ `OJQJo(hHh^`OJQJ^Jo(hHoh^`OJ QJ o(hHh^`OJQJo(hHh^`OJQJ^Jo(hHohPP^P`OJ QJ o(hHh ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h^`.h^`.hpLp^p`L.h@ @ ^@ `.h^`.hL^`L.h^`.h^`.hPLP^P`L.h ^`OJ QJ o(h ^`OJQJo(oh ^`OJ QJ o(h m m ^m `OJQJo(h ==^=`OJQJo(oh   ^ `OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh }}^}`OJ QJ o(P^`P@@^@`.0^`0..``^``... ^` .... ^` ..... ^` ...... `^``....... 00^0`........h^`.h^`.hpLp^p`L.h@ @ ^@ `.h^`.hL^`L.h^`.h^`.hPLP^P`L.h ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(h^`OJQJo(hHh ^`OJ QJ o(hpp^p`OJ QJ o(hHh@ @ ^@ `OJQJo(hHh^`OJQJ^Jo(hHoh^`OJ QJ o(hHh^`OJQJo(hHh^`OJQJ^Jo(hHohPP^P`OJ QJ o(hHh ^`OJ QJ o(h ^`OJQJo(oh pp^p`OJ QJ o(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJ QJ o(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJ QJ o(1<&C-X]W+mP?(%Uasr?y1F7%j":3[s]]mfPGA X>bm |W1|h-x:VW85\PSF*S[;>mDAe|(7)v}&0$UwnZz64%^"EZI-s6]gxace/QnJ;kh],)Zo(8)-311                                                                                 ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry FyData /1TableWordDocument,QSummaryInformation(DocumentSummaryInformation8CompObjj  FMicrosoft Word Document MSWordDocWord.Document.89qRoot Entry F@Db}Data /1TableWordDocument,Q SummaryInformation(DocumentSummaryInformation8CompObjj՜.+,D՜.+,d px   CEFoundations of Software Engineering, Microsoft Research, Redmond, WAUnVA 'Universal Plug and Play Machine Models Title<@ _PID_HLINKS_AdHocReviewCycleID_EmailSubject _AuthorEmail_AuthorEmailDisplayNameA4_Toc5171771414 _Toc5171771294_Toc5171771284_Toc5171771274_Toc5171771264_Toc5171771254_Toc5171771244_Toc5171771234_Toc5171771224_Toc5171771214_Toc5171771204_Toc5171771194_Toc5171771184_Toc5171771174_Toc5171771164_Toc5171771154_Toc5171771144_Toc5171771134_Toc5171771124_Toc5171771114_Toc5171771104_Toc5171771094_Toc5171771084_Toc5171771074_Toc5171771064}_Toc5171771054w_Toc5171771044q_Toc5171771034k_Toc5171771024e_Toc5171771014__Toc5171771005Y_Toc5171770995S_Toc5171770985M_Toc5171770975G_Toc5171770965A_Toc5171770955;_Toc51717709455_Toc5171770935/_Toc5171770925)_Toc5171770915#_Toc5171770905_Toc5171770895_Toc5171770885_Toc5171770875 _Toc5171770865_Toc517177085")Pictures/ChangeDisc.gifm;MSR technical report 2001-59margus@microsoft.comMargus Veanes