
    &`iq                        d Z ddlZddlmZmZmZmZ ddlZddl	m
Z
 ddlmZ ddlmZmZ ddlmZ ddlmZ dd	lmZ dd
lmZmZmZ ddlmZ ddlmZ ddlmZ ddl m!Z! ddl"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+m,Z, ddl-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8 ddl9m:Z: ddl;m<Z< ddl=m>Z>  ej?        e@          ZA G d de          ZB G d de          ZCdS )a  
[1] Mastering Diverse Domains through World Models - 2023
D. Hafner, J. Pasukonis, J. Ba, T. Lillicrap
https://arxiv.org/pdf/2301.04104v1.pdf

[2] Mastering Atari with Discrete World Models - 2021
D. Hafner, T. Lillicrap, M. Norouzi, J. Ba
https://arxiv.org/pdf/2010.02193.pdf
    N)AnyDictOptionalUnion)Self)	Algorithm)AlgorithmConfigNotProvided)DreamerV3Catalog)do_symlog_obs)AddIsFirstsToBatch))report_dreamed_eval_trajectory_vs_samplesreport_predicted_vs_sampled_obs!report_sampling_and_replay_buffer)AddStatesFromEpisodesToBatch)DEFAULT_MODULE_ID)Columns)RLModuleSpec)INPUT_ENV_SINGLE_SPACES)synchronous_parallel_sample)SampleBatch)deep_update)	PublicAPIoverride)ENV_RUNNER_RESULTSLEARN_ON_BATCH_TIMERLEARNER_RESULTSNUM_ENV_STEPS_SAMPLED_LIFETIMENUM_ENV_STEPS_TRAINED_LIFETIMENUM_GRAD_UPDATES_LIFETIMENUM_SYNCH_WORKER_WEIGHTSREPLAY_BUFFER_RESULTSSAMPLE_TIMERSYNCH_WORKER_WEIGHTS_TIMERTIMERS)one_hot)EpisodeReplayBuffer)LearningRateOrSchedulec            .       d    e Zd ZdZd' fd	Z ee           fd            Zed             Z	 ee          e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
ddee         dee         d	ee         d
ee         dee         dee         dee         dee         dee         dee         dee         dee         dee         dee         dee         dee         dee         deeeef                  dee         dee         dee         def, fd            Z ee          e
e
e
ddee         d ee         d!ee         f fd"            Z ee          d( fd#            Z ee          d$             Z ee          defd%            Ze ee          deeef         f fd&                        Z xZS ))DreamerV3Configa4  Defines a configuration class from which a DreamerV3 can be built.

    .. testcode::

        from ray.rllib.algorithms.dreamerv3 import DreamerV3Config
        config = (
            DreamerV3Config()
            .environment("CartPole-v1")
            .training(
                model_size="XS",
                training_ratio=1,
                # TODO
                model={
                    "batch_size_B": 1,
                    "batch_length_T": 1,
                    "horizon_H": 1,
                    "gamma": 0.997,
                    "model_size": "XS",
                },
            )
        )

        config = config.learners(num_learners=0)
        # Build a Algorithm object from the config and run 1 training iteration.
        algo = config.build()
        # algo.train()
        del algo
    Nc                 H   t                                          |pt                     d| _        d| _        dt          d          d| _        d| _        d| _        d| _	        d	| _
        d
| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _         d| _!        d| _"        d| _#        d| _$        dS )z'Initializes a DreamerV3Config instance.)
algo_classXSi   r'   g    .A)typecapacity-C6?giUMu>   @      gffffff?ga2U0*3?gGz?Tg?g     @@g      Y@autoF   NgCl?r   )%super__init__	DreamerV3
model_sizetraining_ratiointreplay_buffer_configworld_model_lractor_lr	critic_lrbatch_size_Bbatch_length_T	horizon_H
gae_lambdaentropy_scalereturn_normalization_decaytrain_critictrain_actorintrinsic_rewards_scale$world_model_grad_clip_by_global_normcritic_grad_clip_by_global_normactor_grad_clip_by_global_norm
symlog_obsuse_float16use_curiosity"metrics_num_episodes_for_smoothing"report_individual_batch_item_statsreport_dream_datareport_images_and_videoslrgammatrain_batch_sizenum_env_runnersrollout_fragment_lengthenable_rl_module_and_learner"enable_env_runner_and_connector_v2use_worker_filter_stats)selfr,   	__class__s     |/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/ray/rllib/algorithms/dreamerv3/dreamerv3.pyr7   zDreamerV3Config.__init__X   sH   J$;)<<< " *C%
 %
! # !*.' '*$4:1/4,.3+  " 34/27/!&(-% 
 $ '($,0)26/ (-$$$    c                     t                                          |||          }| j        r'|                    t          t                                 |S N)r6   build_env_to_module_connector*add_default_connectors_to_learner_pipelineinsert_beforer   r   )r[   envspacesdevice	connectorr\   s        r]   ra   z-DreamerV3Config.build_env_to_module_connector   sW    GG99#vvNN	 : 	##,"$$   r^   c                 $    | j         | j        pdz  S )z`Returns the batch_size_B per Learner worker.

        Needed by some of the DreamerV3 loss math.r5   )r@   num_learners)r[   s    r]   batch_size_B_per_learnerz(DreamerV3Config.batch_size_B_per_learner   s    
  T%6%;!<<r^   )r9   r:   r@   rA   rB   rC   rD   rE   rF   rG   rH   r=   r>   r?   rI   rJ   rK   rL   rM   r<   rN   r9   r:   r@   rA   rB   rC   rD   rE   rF   rG   rH   r=   r>   r?   rI   rJ   rK   rL   rM   r<   rN   returnc                2   |t           urt          d           t                      j        di | |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur|| _	        |t           ur|| _
        |t           ur|| _        |	t           ur|	| _        |
t           ur|
| _        |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur|| _        |t           ur+t/          d| j        id|iddgdg          }|d         | _        | S )a  Sets the training related configuration.

        Args:
            model_size: The main switch for adjusting the overall model size. See [1]
                (table B) for more information on the effects of this setting on the
                model architecture.
                Supported values are "XS", "S", "M", "L", "XL" (as per the paper), as
                well as, "nano", "micro", "mini", and "XXS" (for RLlib's
                implementation). See ray.rllib.algorithms.dreamerv3.utils.
                __init__.py for the details on what exactly each size does to the layer
                sizes, number of layers, etc..
            training_ratio: The ratio of total steps trained (sum of the sizes of all
                batches ever sampled from the replay buffer) over the total env steps
                taken (in the actual environment, not the dreamed one). For example,
                if the training_ratio is 1024 and the batch size is 1024, we would take
                1 env step for every training update: 1024 / 1. If the training ratio
                is 512 and the batch size is 1024, we would take 2 env steps and then
                perform a single training update (on a 1024 batch): 1024 / 2.
            batch_size_B: The batch size (B) interpreted as number of rows (each of
                length `batch_length_T`) to sample from the replay buffer in each
                iteration.
            batch_length_T: The batch length (T) interpreted as the length of each row
                sampled from the replay buffer in each iteration. Note that
                `batch_size_B` rows will be sampled in each iteration. Rows normally
                contain consecutive data (consecutive timesteps from the same episode),
                but there might be episode boundaries in a row as well.
            horizon_H: The horizon (in timesteps) used to create dreamed data from the
                world model, which in turn is used to train/update both actor- and
                critic networks.
            gae_lambda: The lambda parameter used for computing the GAE-style
                value targets for the actor- and critic losses.
            entropy_scale: The factor with which to multiply the entropy loss term
                inside the actor loss.
            return_normalization_decay: The decay value to use when computing the
                running EMA values for return normalization (used in the actor loss).
            train_critic: Whether to train the critic network. If False, `train_actor`
                must also be False (cannot train actor w/o training the critic).
            train_actor: Whether to train the actor network. If True, `train_critic`
                must also be True (cannot train actor w/o training the critic).
            intrinsic_rewards_scale: The factor to multiply intrinsic rewards with
                before adding them to the extrinsic (environment) rewards.
            world_model_lr: The learning rate or schedule for the world model optimizer.
            actor_lr: The learning rate or schedule for the actor optimizer.
            critic_lr: The learning rate or schedule for the critic optimizer.
            world_model_grad_clip_by_global_norm: World model grad clipping value
                (by global norm).
            critic_grad_clip_by_global_norm: Critic grad clipping value
                (by global norm).
            actor_grad_clip_by_global_norm: Actor grad clipping value (by global norm).
            symlog_obs: Whether to symlog observations or not. If set to "auto"
                (default), will check for the environment's observation space and then
                only symlog if not an image space.
            use_float16: Whether to train with mixed float16 precision. In this mode,
                model parameters are stored as float32, but all computations are
                performed in float16 space (except for losses and distribution params
                and outputs).
            replay_buffer_config: Replay buffer config.
                Only serves in DreamerV3 to set the capacity of the replay buffer.
                Note though that in the paper ([1]) a size of 1M is used for all
                benchmarks and there doesn't seem to be a good reason to change this
                parameter.
                Examples:
                {
                "type": "EpisodeReplayBuffer",
                "capacity": 100000,
                }

        Returns:
            This updated AlgorithmConfig object.
        zd`DreamerV3Config.curiosity` is not fully supported and tested yet! It thus remains disabled for now.r<   F )r
   
ValueErrorr6   trainingr9   r:   r@   rA   rB   rC   rD   rE   rF   rG   rH   r=   r>   r?   rI   rJ   rK   rL   rM   r   r<   )r[   r9   r:   r@   rA   rB   rC   rD   rE   rF   rG   rH   r=   r>   r?   rI   rJ   rK   rL   rM   r<   rN   kwargsnew_replay_buffer_configr\   s                           r]   ro   zDreamerV3Config.training   s   D ++4   	""6"""[(((DO,,"0D{** ,D,,"0DK''&DN[(((DO++!.D%[88.HD+{** ,Dk))*D"+55+BD(,,"0D;&&$DMK''&DN/{BB4 5 ++==3RD0)<<2PD/[(((DOk))*D{22 (3')BC')=>'('(( ($ )AAW(XD%r^   )rP   rQ   rR   rP   rQ   rR   c                     t                      j        di | |t          ur|| _        |t          ur|| _        |t          ur|| _        | S )a  Sets the reporting related configuration.

        Args:
            report_individual_batch_item_stats: Whether to include loss and other stats
                per individual timestep inside the training batch in the result dict
                returned by `training_step()`. If True, besides the `CRITIC_L_total`,
                the individual critic loss values per batch row and time axis step
                in the train batch (CRITIC_L_total_B_T) will also be part of the
                results.
            report_dream_data:  Whether to include the dreamed trajectory data in the
                result dict returned by `training_step()`. If True, however, will
                slice each reported item in the dream data down to the shape.
                (H, B, t=0, ...), where H is the horizon and B is the batch size. The
                original time axis will only be represented by the first timestep
                to not make this data too large to handle.
            report_images_and_videos: Whether to include any image/video data in the
                result dict returned by `training_step()`.
            **kwargs:

        Returns:
            This updated AlgorithmConfig object.
        rm   )r6   	reportingr
   rP   rQ   rR   )r[   rP   rQ   rR   rp   r\   s        r]   rs   zDreamerV3Config.reportingN  s`    > 	##F###-[@@6XD3K//%6D"#;66,DD)r^   c                 (   t                                                       | j        r|                     d           | j        s|                     d           | j        dk    r9| j        | j        z  dk    r&|                     d| j         d| j         d           | j        r| j        s|                     d           | j	        |                     d	           | j
                            d
          dk    r|                     d           d S d S )Nz2DreamerV3 does NOT support multi-agent setups yet!zQDreamerV3 must be run with `config.api_stack(enable_rl_module_and_learner=True)`!r5   r   zYour `batch_size_B` (z() must be a multiple of `num_learners` (zZ) in order for DreamerV3 to be able to split batches evenly across your Learner processes.zCannot train actor network (`train_actor=True`) w/o training critic! Make sure you either set `train_critic=True` or `train_actor=False`.zV`train_batch_size` should NOT be set! Use `batch_size_B` and `batch_length_T` instead.r.   r'   zPDreamerV3 must be run with the `EpisodeReplayBuffer` type! None other supported.)r6   validateis_multi_agent_value_errorrX   ri   r@   rG   rF   rU   r<   getr[   r\   s    r]   ru   zDreamerV3Config.validatex  sz    	  	TRSSS 0 	7   q  d&7$:K&Kq&P&P(9  #'#4      	D$5 	W  
  ,,  
 $((004III#     JIr^   c                 X    | j         dk    rddlm} |S t          d| j          d          )Ntorchr   )DreamerV3TorchLearnerThe framework  is not supported.)framework_str<ray.rllib.algorithms.dreamerv3.torch.dreamerv3_torch_learnerr|   rn   )r[   r|   s     r]   get_default_learner_classz)DreamerV3Config.get_default_learner_class  sS    ((      )(Td.@TTTUUUr^   c                     | j         dk    rddlm} nt          d| j          d          t	          |t
                    S )Nr{   r   )DreamerV3TorchRLModuler}   r~   )module_classcatalog_class)r   >ray.rllib.algorithms.dreamerv3.torch.dreamerv3_torch_rl_moduler   rn   r   r   )r[   modules     r]   get_default_rl_module_specz*DreamerV3Config.get_default_rl_module_spec  sf    ((      
 Td.@TTTUUU?OPPPPr^   c                 z    t                      j        | j        | j        | j        | j        | j        | j        dz  S )N)rT   rB   r9   rL   rM   rA   )r6   _model_config_auto_includesrT   rB   r9   rL   rM   rA   ry   s    r]   r   z+DreamerV3Config._model_config_auto_includes  sC     ww2Z//+"16
 6
 
 	
r^   r`   rk   N)__name__
__module____qualname____doc__r7   r   r	   ra   propertyrj   r
   r   strfloatr;   boolr(   r   dictr   ro   rs   ru   r   r   r   r   r   r   __classcell__r\   s   @r]   r*   r*   :   s        :;- ;- ;- ;- ;- ;-~ Xo     = = X= Xo %0*5&1(3#.&1)46A'2&13>;F5@6A@K;F:E1<&1/:(3/^ ^ ^ SM^ !	^
 sm^ !^ C=^ UO^  ^ %-UO^ tn^ d^^ "*%^ !!78^ 12^  23!^" /7uo#^$ *2%%^& )1'^( U49-.)^* d^+^, 'tn-^.  ~/^2 
3^ ^ ^ ^ ^ ^@ Xo >I,73>' ' ' -5TN' $D>	'
 #+4.' ' ' ' ' 'R Xo* * * * * *X XoV V V Xo	QL 	Q 	Q 	Q 	Q Xo
T#s(^ 
 
 
 
 
  X
 
 
 
 
r^   r*   c                       e Zd ZdZ ee          d             Ze ee          defd                        Z	 ee          de
f fd            Z ee          dd            Zedefd	            Zed fd
            Z xZS )r8   zJImplementation of the model-based DreamerV3 RL algorithm described in [1].c                      t          d          )NzDreamerV3 does not support the `compute_single_action()` API. Refer to the README here (https://github.com/ray-project/ray/tree/master/rllib/algorithms/dreamerv3) to find more information on how to run action inference with this algorithm.)NotImplementedError)r[   argsrp   s      r]   compute_single_actionzDreamerV3.compute_single_action  s    !-
 
 	
r^   rk   c                     t                      S r`   )r*   )clss    r]   get_default_configzDreamerV3.get_default_config  s        r^   configc                     t                                          |           t          | j        j        d         | j        j        | j        j                  | _        d S )Nr/   )r/   r@   rA   )r6   setupr'   r   r<   r@   rA   replay_buffer)r[   r   r\   s     r]   r   zDreamerV3.setup  sU    f 1[5jA1;5
 
 
r^   Nc                    | j         dk    r5t                              d| j        j        | j        j        z   d           d}| j                            t          t          f          5  | j
                                        | j        j        | j        j        z  k     s| j        | j        j        k    s|st          | j        | j        j        | j        j        z  | j        j        dd          \  }}| j                            |t&                     | j
                            |           d}t+          d	 |D                       }|}| j                            t&          t.          fd
          dk    rt          | j        | j        j        | j        j        z  |z
  | j        j        ddd          \  }}| j                            |t&                     | j
                            |           |t+          d |D                       z  }| j
                                        | j        j        | j        j        z  k     | j        | j        j        k    |d d d            n# 1 swxY w Y   t1          | j        | j
                   | j                                        }| j                            |gt6                     | j        t:                   \  }	}
dx}}||z  | j        j        k     r| j                            t          t<          f          5  t                              d| j          d| d           | j
                            | j        j        | j        j                  }| j        j        | j        j        z  }||z  }tA          |
tB          j        j"                  r>|tF          j$                 |d<   tK          |d         |
j&                  |tF          j$        <   | j'        (                    tS          |          *                                t.          | j                            t&          t.          fd
          i          }| j                            |tV                     |dz  }| j        ,                    tZ          dd           d d d            n# 1 swxY w Y   ||z  | j        j        k     t]          | j        || j        j        | j        j        t_          |	| j        j0                  | j        j1        o| j         dz  dk               te          | j        |d| j        j3        dz   | j4        j5        j6        t_          |	| j        j0                  | j        j7        o| j         dz  dk    | j        j8                   | j                            t          tr          f          5  | j        ,                    tt          dd           | j        ;                    | j'        d           d d d            n# 1 swxY w Y   | j        ,                    d| j        d           d S )Nr   z.Filling replay buffer so it contains at least z/ timesteps (required for a single train batch).FT)
worker_setmax_agent_stepssample_timeout_s_uses_new_env_runners_return_metrics)key)episodesc              3   4   K   | ]}t          |          V  d S r`   len.0epss     r]   	<genexpr>z*DreamerV3.training_step.<locals>.<genexpr>  s(      3Q3QCHH3Q3Q3Q3Q3Q3Qr^   default)r   r   r   random_actionsr   r   c              3   4   K   | ]}t          |          V  d S r`   r   r   s     r]   r   z*DreamerV3.training_step.<locals>.<genexpr>5  s(      (G(GcS(G(G(G(G(G(Gr^   )metricsr   z	Sub-iteration /))r@   rA   actions_ints)depth)batch	timestepsr5   lifetime_sum)reduced   )r   sampler@   rA   rL   	do_report)r   r   	burn_in_T	dreamed_Tdreamer_modelrL   r   	frameworksum)from_worker_or_learner_groupinference_onlyactual_training_ratio)window)<training_iterationloggerinfor   r@   rA   r   log_timer%   r#   r   get_num_timestepsr:   r   env_runner_grouprW   num_envs_per_env_runnerr   	aggregater   addr   peekr   r   local_replay_bufferget_metricsr"   re   r   r   r   
isinstancegymDiscreter   ACTIONSr&   nlearner_groupupdater   as_multi_agentr   	log_valuer    r   r   rL   rR   r   rB   
env_runnerr   r   rQ   r   r$   r!   sync_weights)r[   have_sampledr   env_runner_resultsenv_steps_last_regular_sampletotal_sampled	_episodes_env_runner_resultsreplay_buffer_resultssingle_observation_spacesingle_action_spacereplayed_steps_this_itersub_iterr   replayed_stepslearner_resultss                   r]   training_stepzDreamerV3.training_step  su    "a''KK7;+dk.HH7 7 7   \""FL#9:: ;	H ;	H "4466;+dk.HHJ J &$+*DDD# E
 0K#4;+=> &*[%A*.$(	0 	0 	0,, &&'9?Q&RRR
 "&&&999# 143Q3Q3Q3Q3Q0Q0Q- =
 L%%+-KL ! &   	  6Q#'#8 K4t{7QQ;< *.)E'+.2(,
6 
6 
62I2 L**+>DV*WWW&**I*>>>!S(G(GY(G(G(G%G%GGMk "4466;+dk.HHJ J &$+*DDD# E;	H ;	H ;	H ;	H ;	H ;	H ;	H ;	H ;	H ;	H ;	H ;	H ;	H ;	H ;	H| 	*L0B	
 	
 	
 	
 !% 8 D D F F 56<QRRR 9=#9
5 "5 /0/ 8$'DDK&' ' &&0D'EFF % %Tt/FTTTTTUUU +22!%!9#';#= 3   "&!9DK<V!V(N:(13:3FGG -3GO-DF>*.5~.13/ / /F7?+ #'"4";";%f--<<>> 78I8I/1OP$% 9J 9 9 #< # # &&O&LLLA&&-q '   G% % % % % % % % % % % % % % % %'DDK&' '^ 	(L1;5$(& 
 4 7+c1Q6	
 	
 	
 	
* 	2Lk+a//0>$(& 
 -T$2IC2OST2Tk/	
 	
 	
 	
$ \""F,F#GHH 	 	 L""#;Qu"MMM!..-1-?# /   	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	68KTUVVVVVs9   )G6I++I/2I/FR--R14R1AXXXc                     d}| j                             t          d          | j                             t          t          f|          p|z  S )a  Returns the actual training ratio of this Algorithm (not the configured one).

        The training ratio is copmuted by dividing the total number of steps
        trained thus far (replayed from the buffer) over the total number of actual
        env steps taken thus far.
        r0   r   r   )r   r   r   r   r   )r[   r   s     r]   r:   zDreamerV3.training_ratio  s\     |  !? KK!!')GH "    
 	
r^   c                 @   t                                          |           | j        j        rnt	          | j        j                  t	          | j        j        j        t                             k    sJ | j        j        j        t                   | j        _        dS dS )a  Sts the algorithm to the provided state

        Args:
            state: The state dictionary to restore this `DreamerV3` instance to.
                `state` may have been returned by a call to an `Algorithm`'s
                `__getstate__()` method.
        )stateN)
r6   __setstate__r   +share_module_between_env_runner_and_learneridr   r   r   _learnerr   )r[   r   r\   s     r]   r   zDreamerV3.__setstate__  s     	5))) ;B 	do,--"+23DE2 2     &*%7%@%G!&DO"""		 	r^   r   )r   r   r   r   r   r   r   classmethodr*   r   r	   r   r   r   r   r:   r   r   r   r   s   @r]   r8   r8     sH       TT Xi
 
 
 Xi!? ! ! !  [! Xi
O 
 
 
 
 
 
$ XiAW AW AW AWF 
 
 
 
 X
&      Y    r^   r8   )Dr   loggingtypingr   r   r   r   	gymnasiumr   typing_extensionsr   ray.rllib.algorithms.algorithmr   %ray.rllib.algorithms.algorithm_configr	   r
   0ray.rllib.algorithms.dreamerv3.dreamerv3_catalogr   $ray.rllib.algorithms.dreamerv3.utilsr   ;ray.rllib.algorithms.dreamerv3.utils.add_is_firsts_to_batchr   .ray.rllib.algorithms.dreamerv3.utils.summariesr   r   r   ray.rllib.connectors.commonr   ray.rllib.corer   ray.rllib.core.columnsr   "ray.rllib.core.rl_module.rl_moduler   ray.rllib.envr   ray.rllib.execution.rollout_opsr   ray.rllib.policy.sample_batchr   ray.rllib.utilsr   ray.rllib.utils.annotationsr   r   ray.rllib.utils.metricsr   r   r   r   r   r    r!   r"   r#   r$   r%   ray.rllib.utils.numpyr&   4ray.rllib.utils.replay_buffers.episode_replay_bufferr'   ray.rllib.utils.typingr(   	getLoggerr   r   r*   r8   rm   r^   r]   <module>r     s     - - - - - - - - - - - -     " " " " " " 4 4 4 4 4 4 N N N N N N N N M M M M M M > > > > > >              
 E D D D D D , , , , , , * * * * * * ; ; ; ; ; ; 1 1 1 1 1 1 G G G G G G 5 5 5 5 5 5 ' ' ' ' ' ' ; ; ; ; ; ; ; ;                          * ) ) ) ) ) T T T T T T 9 9 9 9 9 9		8	$	$L
 L
 L
 L
 L
o L
 L
 L
^S S S S S	 S S S S Sr^   