U
    ‰dñ  ã                   @   sf   d dl mZ d dlmZ d dlmZ d dlZd dlm	Z	 d dl
Z
e
 e¡Zdd„ ZG dd	„ d	eƒZdS )
é    )Úschema)Ú
ModelLayer)Ú	viewitemsN)Údefaultdictc                    s¦   t tƒ}d‰ | D ]€}|jjd }t|dƒrˆt|jdƒrˆt|jjdƒrˆt|jjjt	ƒrˆ|jjj 
¡ D ]$\}}||  ‡ fdd„|D ƒ¡ qbˆ |7 ‰ q| ¡ r¢t	|ƒS d S )Nr   ÚmetadataÚfeature_specsÚfeature_to_indexc                    s   g | ]}ˆ | ‘qS © r	   )Ú.0Úvi©Z	start_posr	   ú?/tmp/pip-unpacked-wheel-ua33x9lu/caffe2/python/layers/concat.pyÚ
<listcomp>   s     z5get_concatenated_feature_to_index.<locals>.<listcomp>)r   ÚlistZdtypeÚshapeÚhasattrr   r   Ú
isinstancer   ÚdictÚitemsÚextendÚkeys)Zblobs_to_concatZconcat_feature_to_indexZscalarZnum_dimsÚkÚvr	   r   r   Ú!get_concatenated_feature_to_index   s    

ÿþý
r   c                       s*   e Zd ZdZd	‡ fdd„	Zdd„ Z‡  ZS )
ÚConcataÿ  
    Construct Concat layer
    Assume that first dimension is batch,

    Example:

        embedding_dim = 64
        input_record = self.new_record(schema.Struct(
            ('input1', schema.Scalar((np.float32, (embedding_dim, )))),
            ('input2', schema.Scalar((np.float32, (embedding_dim, )))),
            ('input3', schema.Scalar((np.float32, (embedding_dim, )))),
        ))

        output = self.model.Concat(input_record)
        self.assertEqual(
            schema.Scalar((np.float32, ((len(input_record.fields) * embedding_dim, )))),
            output
        )

        # Note that in Concat layer we assume first dimension is batch.
        # so input is B * embedding_dim
        # add_axis=1 make it B * 1 * embedding_dim
        # Concat on axis=1 make it B * N * embedding_dim

        output = self.model.Concat(input_record, axis=1, add_axis=1)
        self.assertEqual(
            schema.Scalar((np.float32, ((len(input_record.fields), embedding_dim)))),
            output
        )
    é   r   Úconcatc                    sÎ  t t| ƒj|||f|Ž || _|| _|dkr<|dkr<tdƒ‚t|tjƒsVtd 	|¡ƒ‚g }t
|jƒD ]d\}}	t|	tjƒsˆtd 	||	¡ƒ‚t|	 ¡ jƒ}
|rª|
 |d d¡ t|
ƒ|ks¾tdƒ‚| |
¡ qdt dt|ƒ ¡ |dkrt |d |  d¡g¡| _d S d}|D ]D}
||
|d  7 }d|
|d < |
|d kstd	 	|
|d ¡ƒ‚q|d }|||d < t d
t|ƒ ¡ t tj|f|  d¡¡| _|j ¡ }t|ƒ}|rÊtjtj|dd}| j |¡ d S )Nr   r   zIt's not allowed to add axis=0z8Incorrect input type. Expected Struct, but received: {0}z9Incorrect input type for {}. Expected Scalar, but got: {}z:Concat expects that limited dimensions of the input tensorzConcat Layer input shapes: Úoutputz0Shapes {0} and {1} are not compatible for ConcatzConcat Layer output_dims: )r   )r   ) Úsuperr   Ú__init__ÚaxisÚadd_axisÚAssertionErrorr   r   ÚStructÚformatr   ÚfieldsZScalarr   Ú
field_typer   ÚinsertÚlenÚappendÚloggerÚinfoÚstrZfrom_blob_listZget_next_blob_referenceÚoutput_schemaÚnpZfloat32Úvaluesr   ZMetadataZFeatureSpecZset_metadata)ÚselfÚmodelÚinput_recordr    r!   ÚnameÚkwargsZshapesÚ
field_namer&   r   Z
concat_dimZoutput_dimsZrecord_to_concatZconcated_feature_to_indexr   ©Ú	__class__r	   r   r   C   sz    ÿÿÿ ÿÿÿ

þ ÿÿþ
ÿÿÿzConcat.__init__c                 C   s<   |j | j ¡ | j ¡ d | j ¡ d d g| j| jd d S )Nr   Z_concat_dims)r    r!   )r   r2   Zfield_blobsr-   r    r!   )r0   Únetr	   r	   r   Úadd_ops€   s    þùzConcat.add_ops)r   r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r9   Ú__classcell__r	   r	   r6   r   r   #   s
     ÿ=r   )Zcaffe2.pythonr   Zcaffe2.python.layers.layersr   Zfuture.utilsr   Znumpyr.   Úcollectionsr   ÚloggingÚ	getLoggerr:   r*   r   r   r	   r	   r	   r   Ú<module>   s   
