Repository: MilaNLProc/contextualized-topic-models (language: python)

Issue:
Updating develop



Discussion / hints:

Fix patch:
diff --git a/README.rst b/README.rst
index 489a7a7..f78c54b 100644
--- a/README.rst
+++ b/README.rst
@@ -100,6 +100,9 @@ You can look at our `medium`_ blog post or start from one of our Colab Tutorials
     :target: https://colab.research.google.com/drive/1NWTC-w9YZ6knESynVyK4zhoP1h2tTyZw?usp=sharing
     :alt: Open In Colab  
 
+.. |colab3_3| image:: https://colab.research.google.com/assets/colab-badge.svg
+    :target: https://colab.research.google.com/drive/1upTRu4zSm1VMbl633n9qkIDA526l22E_?usp=sharing
+    :alt: Open In Colab
 
 +--------------------------------------------------------------------------------+------------------+
 | Name                                                                           | Link             |
@@ -108,7 +111,7 @@ You can look at our `medium`_ blog post or start from one of our Colab Tutorials
 +--------------------------------------------------------------------------------+------------------+
 | Zero-Shot Cross-lingual Topic Modeling (Preproc+Viz) (stable **v2.0.0**)       | |colab2_2|       |
 +--------------------------------------------------------------------------------+------------------+
-| Supervised and β-CombinedTM (stable **v2.0.0**)                                | |colab3_3|       |
+| SuperCTM and  β-CTM (High-level usage) (stable **v2.1.0**)                     | |colab3_3|       |
 +--------------------------------------------------------------------------------+------------------+
 
 Overview
@@ -227,7 +230,6 @@ Here is how you can use the CombinedTM. This is a standard topic model that also
     from contextualized_topic_models.models.ctm import CombinedTM
     from contextualized_topic_models.utils.data_preparation import TopicModelDataPreparation
     from contextualized_topic_models.utils.data_preparation import bert_embeddings_from_file
-    from contextualized_topic_models.datasets.dataset import CTMDataset
 
     qt = TopicModelDataPreparation("paraphrase-distilroberta-base-v2")
 
@@ -254,7 +256,6 @@ More interestingly, this model can be used for cross-lingual topic modeling (See
     from contextualized_topic_models.models.ctm import ZeroShotTM
     from contextualized_topic_models.utils.data_preparation import TopicModelDataPreparation
     from contextualized_topic_models.utils.data_preparation import bert_embeddings_from_file
-    from contextualized_topic_models.datasets.dataset import CTMDataset
 
     text_for_contextual = [
         "hello, this is unpreprocessed text you can give to the model",
@@ -353,6 +354,65 @@ is covered by **paraphrase-multilingual-mpnet-base-v2**).
 **Advanced Notes:** We do not need to pass the Spanish bag of word: the bag of words of the two languages will not be comparable! We are passing it to the model for compatibility reasons, but you cannot get
 the output of the model (i.e., the predicted BoW of the trained language) and compare it with the testing language one.
 
+Extensions
+----------
+
+We have developed two extensions to CTM, one that supports supervision and another one that
+uses a weight on the KL loss to generate disentangled representations.
+
+**NOTE**: both model haven't been thoroughly validated. Use them with care and let us know if you find something cool!
+
+SuperCTM
+~~~~~~~~
+
+Inspiration for SuperCTM has been taken directly from the work by `Card et al., 2018 <https://aclanthology.org/P18-1189/>`_ (you can read this as
+"we essentially implemented their approach in our architecture"). SuperCTM should give better representations of the documents - this is somewhat expected, since we are using the labels to give more information to the model - and in theory should also make the model able to find topics more coherent with respect to the labels.
+The model is super easy to use and requires minor modifications to the already implemented pipeline:
+
+
+.. code-block:: python
+
+    from contextualized_topic_models.models.ctm import ZeroShotTM
+    from contextualized_topic_models.utils.data_preparation import TopicModelDataPreparation
+
+    text_for_contextual = [
+        "hello, this is unpreprocessed text you can give to the model",
+        "have fun with our topic model",
+    ]
+
+    text_for_bow = [
+        "hello unpreprocessed give model",
+        "fun topic model",
+    ]
+
+    labels = [0, 1] # we need to have  a label for each document
+
+    qt = TopicModelDataPreparation("paraphrase-multilingual-mpnet-base-v2")
+
+    # training dataset should contain the labels
+    training_dataset = qt.fit(text_for_contextual=text_for_contextual, text_for_bow=text_for_bow, labels=labels)
+
+    # model should know the label size in advance
+    ctm = CombinedTM(bow_size=len(qt.vocab), contextual_size=768, n_components=50, label_size=len(set(labels)))
+
+    ctm.fit(training_dataset) # run the model
+
+    ctm.get_topics(2)
+
+
+β-CTM
+~~~~~~
+
+We also implemented the intuition found in the work by `Higgins et al., 2018 <https://openreview.net/forum?id=Sy2fzU9gl>`_, where a weight is applied
+to the KL loss function. The idea is that giving more weight to the KL part of the loss function helps in creating disentangled representations
+by forcing independence in the components. Again, the model should be straightforward to use:
+
+.. code-block:: python
+
+     ctm = CombinedTM(bow_size=len(qt.vocab), contextual_size=768, n_components=50, loss_weights={"beta" : 3})
+
+
+
 
 Visualization
 -------------
diff --git a/contextualized_topic_models/data/gnews/GoogleNews_LABEL.txt b/contextualized_topic_models/data/gnews/GoogleNews_LABEL.txt
new file mode 100644
index 0000000..45e4dc0
--- /dev/null
+++ b/contextualized_topic_models/data/gnews/GoogleNews_LABEL.txt
@@ -0,0 +1,11108 @@
+65
+96
+72
+140
+89
+75
+48
+99
+48
+19
+20
+66
+93
+21
+1
+80
+87
+71
+80
+8
+73
+98
+79
+62
+85
+29
+104
+140
+31
+106
+118
+65
+38
+43
+96
+2
+91
+14
+62
+6
+128
+61
+104
+33
+148
+17
+16
+71
+88
+95
+32
+52
+74
+17
+88
+15
+11
+53
+21
+11
+86
+33
+4
+117
+80
+88
+150
+112
+56
+88
+40
+63
+44
+70
+1
+81
+13
+9
+10
+17
+29
+11
+27
+76
+77
+90
+32
+92
+64
+89
+97
+73
+91
+89
+21
+50
+75
+48
+8
+85
+130
+91
+48
+48
+21
+131
+91
+62
+62
+134
+16
+15
+6
+144
+29
+89
+11
+141
+4
+10
+42
+120
+143
+68
+140
+134
+86
+94
+87
+16
+92
+128
+85
+66
+33
+39
+95
+30
+13
+74
+1
+91
+26
+130
+62
+74
+97
+48
+129
+121
+15
+42
+90
+89
+1
+62
+69
+8
+118
+42
+27
+64
+68
+79
+19
+87
+127
+25
+148
+147
+4
+73
+148
+53
+28
+11
+66
+93
+53
+1
+151
+91
+2
+83
+70
+43
+96
+48
+93
+150
+67
+46
+21
+5
+68
+65
+119
+39
+13
+95
+91
+129
+77
+64
+83
+74
+33
+51
+141
+135
+79
+62
+68
+98
+6
+21
+91
+77
+65
+149
+44
+91
+140
+98
+150
+1
+73
+17
+42
+70
+30
+96
+59
+148
+139
+50
+18
+3
+29
+13
+31
+77
+42
+128
+63
+146
+46
+21
+21
+1
+139
+77
+48
+69
+48
+65
+2
+98
+69
+39
+52
+2
+124
+28
+25
+62
+6
+146
+87
+146
+113
+77
+143
+118
+106
+148
+66
+67
+77
+106
+128
+68
+27
+93
+76
+30
+6
+104
+14
+63
+33
+17
+148
+29
+15
+38
+64
+86
+83
+108
+121
+30
+129
+76
+131
+93
+54
+20
+52
+17
+12
+87
+29
+139
+1
+48
+53
+29
+68
+114
+68
+73
+38
+77
+73
+75
+44
+67
+110
+46
+42
+17
+63
+14
+48
+89
+67
+139
+86
+85
+78
+140
+83
+43
+93
+89
+77
+29
+122
+42
+88
+6
+87
+29
+17
+2
+98
+16
+86
+64
+90
+7
+93
+2
+146
+65
+74
+66
+68
+91
+93
+17
+42
+52
+33
+76
+65
+88
+89
+48
+72
+68
+48
+26
+114
+33
+42
+122
+140
+43
+147
+26
+48
+89
+91
+135
+71
+42
+129
+65
+77
+67
+67
+96
+65
+48
+149
+15
+6
+71
+30
+11
+43
+127
+42
+74
+21
+65
+76
+62
+1
+64
+86
+91
+77
+4
+21
+87
+20
+19
+43
+18
+53
+91
+60
+149
+2
+68
+77
+33
+22
+70
+68
+1
+30
+71
+43
+42
+79
+65
+124
+64
+70
+16
+98
+98
+11
+87
+102
+4
+146
+73
+91
+130
+79
+140
+1
+91
+127
+42
+69
+12
+63
+30
+88
+93
+11
+18
+85
+48
+21
+21
+10
+120
+87
+53
+14
+111
+112
+43
+16
+77
+129
+41
+147
+89
+8
+77
+61
+1
+12
+70
+53
+18
+100
+1
+128
+1
+8
+96
+61
+21
+98
+98
+1
+15
+70
+33
+75
+105
+144
+16
+21
+18
+42
+42
+86
+129
+15
+74
+129
+118
+57
+4
+80
+91
+43
+17
+77
+52
+51
+8
+104
+89
+42
+17
+5
+68
+100
+46
+131
+53
+21
+2
+93
+88
+46
+142
+65
+95
+98
+12
+48
+62
+42
+68
+83
+116
+133
+42
+19
+86
+119
+42
+77
+12
+31
+41
+6
+129
+63
+92
+38
+98
+86
+11
+14
+42
+24
+2
+32
+14
+14
+1
+21
+32
+129
+38
+2
+68
+140
+8
+17
+67
+42
+129
+65
+48
+67
+136
+31
+41
+42
+64
+140
+77
+7
+128
+17
+37
+89
+95
+23
+6
+69
+77
+87
+11
+139
+53
+94
+148
+142
+79
+50
+1
+68
+33
+116
+65
+148
+69
+49
+3
+141
+68
+2
+21
+48
+43
+75
+66
+107
+146
+140
+21
+62
+14
+27
+65
+27
+11
+149
+139
+70
+8
+62
+77
+95
+48
+21
+140
+74
+81
+4
+64
+42
+33
+140
+141
+18
+45
+61
+52
+4
+8
+62
+93
+71
+25
+131
+89
+33
+37
+127
+98
+90
+73
+64
+149
+48
+135
+69
+68
+72
+8
+14
+28
+30
+25
+21
+68
+4
+127
+85
+129
+1
+2
+62
+36
+4
+66
+79
+89
+139
+89
+68
+42
+27
+3
+53
+42
+105
+30
+140
+18
+69
+48
+53
+62
+41
+127
+125
+70
+42
+65
+147
+90
+7
+70
+89
+77
+140
+67
+53
+149
+74
+139
+92
+96
+77
+73
+18
+54
+91
+68
+14
+108
+77
+75
+14
+1
+124
+91
+48
+21
+140
+64
+62
+74
+150
+67
+57
+89
+143
+6
+80
+129
+121
+15
+8
+129
+65
+1
+90
+105
+83
+145
+4
+98
+10
+18
+41
+121
+89
+48
+64
+127
+61
+42
+65
+6
+141
+93
+77
+17
+48
+16
+91
+77
+44
+10
+124
+7
+76
+29
+68
+80
+123
+53
+36
+107
+13
+104
+27
+8
+65
+42
+105
+7
+89
+6
+16
+118
+89
+43
+8
+27
+90
+101
+59
+27
+38
+74
+48
+2
+1
+21
+16
+68
+15
+77
+87
+38
+2
+64
+124
+69
+41
+77
+100
+95
+8
+42
+4
+121
+42
+68
+96
+8
+14
+70
+8
+7
+32
+77
+21
+42
+6
+1
+29
+53
+17
+46
+95
+102
+73
+15
+88
+71
+17
+21
+33
+21
+12
+91
+97
+88
+15
+29
+24
+38
+77
+133
+143
+70
+65
+79
+75
+65
+43
+24
+1
+79
+65
+12
+96
+128
+95
+51
+104
+48
+66
+68
+53
+77
+42
+52
+18
+68
+77
+18
+1
+68
+86
+64
+17
+5
+66
+127
+21
+93
+27
+66
+121
+90
+21
+113
+22
+22
+93
+70
+16
+21
+91
+14
+41
+38
+112
+73
+42
+25
+6
+21
+17
+87
+129
+121
+148
+68
+129
+41
+25
+42
+68
+125
+92
+11
+46
+53
+139
+68
+48
+89
+98
+85
+116
+48
+79
+143
+68
+51
+129
+137
+129
+17
+89
+94
+10
+17
+139
+88
+91
+96
+42
+91
+129
+56
+11
+74
+119
+54
+16
+63
+73
+1
+121
+89
+20
+91
+43
+42
+74
+62
+42
+89
+87
+129
+29
+17
+69
+93
+75
+11
+149
+124
+140
+62
+77
+74
+149
+90
+21
+89
+138
+134
+48
+8
+82
+16
+8
+19
+72
+42
+7
+60
+87
+48
+91
+133
+142
+30
+133
+37
+42
+132
+84
+77
+91
+119
+148
+120
+105
+89
+91
+104
+38
+120
+18
+49
+88
+74
+68
+104
+129
+129
+13
+12
+144
+2
+63
+42
+149
+46
+65
+87
+16
+43
+97
+21
+86
+46
+66
+121
+1
+89
+129
+79
+10
+21
+4
+124
+100
+89
+64
+85
+65
+90
+18
+104
+17
+48
+140
+68
+14
+98
+150
+96
+65
+96
+18
+143
+89
+90
+68
+74
+102
+65
+68
+74
+96
+149
+8
+79
+48
+42
+79
+70
+29
+13
+77
+74
+70
+50
+98
+38
+42
+119
+21
+74
+48
+86
+27
+70
+8
+48
+87
+48
+77
+86
+89
+68
+68
+6
+64
+73
+65
+79
+8
+90
+141
+46
+75
+6
+15
+103
+129
+8
+38
+136
+93
+51
+70
+16
+14
+62
+144
+88
+88
+21
+105
+98
+75
+2
+141
+44
+89
+21
+99
+139
+6
+67
+46
+43
+2
+70
+64
+147
+46
+17
+89
+118
+48
+42
+83
+122
+62
+143
+76
+14
+129
+8
+27
+53
+7
+151
+76
+6
+140
+39
+72
+69
+29
+42
+44
+65
+148
+12
+106
+51
+80
+91
+21
+87
+68
+42
+43
+42
+135
+71
+8
+87
+21
+66
+67
+21
+8
+9
+26
+74
+77
+16
+77
+18
+124
+149
+69
+127
+18
+140
+4
+29
+130
+48
+93
+142
+142
+4
+68
+38
+6
+13
+44
+87
+68
+87
+84
+69
+26
+91
+118
+86
+27
+79
+8
+48
+70
+132
+52
+93
+79
+73
+142
+142
+79
+91
+94
+139
+4
+74
+48
+38
+48
+86
+133
+77
+66
+13
+74
+43
+38
+110
+88
+29
+76
+42
+90
+63
+86
+65
+143
+1
+93
+15
+77
+46
+21
+16
+91
+53
+53
+77
+5
+9
+14
+8
+2
+21
+48
+83
+89
+114
+85
+93
+5
+88
+44
+81
+90
+37
+42
+73
+42
+71
+73
+60
+149
+99
+89
+89
+82
+15
+91
+99
+25
+27
+73
+83
+63
+77
+102
+53
+127
+96
+89
+21
+73
+8
+42
+94
+114
+48
+97
+128
+61
+85
+95
+121
+89
+71
+89
+29
+46
+17
+96
+9
+88
+53
+8
+75
+151
+91
+21
+71
+6
+132
+68
+61
+68
+129
+78
+15
+27
+68
+129
+7
+101
+74
+83
+121
+1
+25
+68
+18
+73
+74
+77
+74
+80
+105
+30
+140
+73
+98
+17
+47
+124
+42
+120
+73
+13
+91
+42
+93
+42
+62
+79
+87
+139
+62
+64
+107
+42
+128
+142
+15
+42
+77
+65
+57
+21
+75
+6
+93
+139
+70
+95
+149
+58
+68
+48
+14
+43
+15
+74
+80
+15
+66
+67
+113
+21
+30
+86
+22
+68
+21
+71
+96
+146
+121
+91
+118
+1
+133
+62
+27
+128
+42
+16
+10
+8
+68
+30
+44
+105
+42
+8
+59
+96
+68
+63
+89
+91
+131
+80
+74
+131
+150
+98
+139
+91
+65
+33
+127
+1
+61
+127
+34
+1
+105
+89
+29
+112
+64
+85
+8
+130
+87
+15
+146
+31
+132
+21
+42
+77
+73
+91
+48
+86
+87
+48
+148
+48
+80
+24
+7
+21
+129
+21
+13
+68
+80
+48
+90
+93
+48
+11
+64
+9
+46
+8
+69
+129
+89
+29
+77
+139
+46
+87
+129
+34
+93
+67
+89
+68
+1
+48
+142
+130
+140
+21
+87
+121
+146
+33
+80
+96
+23
+3
+2
+7
+87
+68
+62
+53
+21
+53
+24
+68
+10
+1
+97
+70
+34
+6
+26
+12
+148
+27
+89
+76
+139
+42
+76
+79
+114
+93
+61
+143
+2
+64
+127
+91
+69
+95
+21
+15
+42
+96
+51
+1
+53
+73
+98
+64
+91
+9
+93
+8
+1
+27
+91
+91
+91
+143
+139
+53
+128
+145
+77
+25
+14
+80
+87
+79
+68
+66
+21
+66
+42
+97
+42
+65
+139
+27
+74
+65
+1
+16
+8
+68
+77
+80
+78
+9
+77
+98
+8
+95
+66
+15
+6
+129
+89
+97
+140
+124
+32
+44
+95
+18
+48
+21
+10
+14
+70
+87
+68
+52
+11
+11
+87
+87
+17
+61
+88
+121
+8
+28
+80
+91
+46
+70
+102
+90
+98
+14
+75
+25
+77
+42
+73
+30
+17
+98
+117
+99
+73
+26
+46
+129
+121
+96
+144
+4
+3
+64
+17
+79
+68
+94
+70
+88
+83
+119
+48
+140
+1
+31
+70
+42
+42
+104
+15
+19
+151
+38
+152
+89
+21
+37
+48
+91
+98
+17
+77
+6
+30
+1
+89
+1
+111
+53
+96
+139
+53
+77
+2
+43
+131
+85
+21
+101
+65
+89
+62
+62
+89
+1
+73
+124
+84
+48
+21
+152
+46
+17
+27
+77
+17
+66
+99
+27
+127
+77
+53
+98
+61
+49
+94
+30
+127
+42
+119
+41
+79
+70
+109
+21
+131
+121
+89
+75
+21
+62
+8
+89
+26
+18
+74
+10
+7
+73
+38
+30
+61
+75
+71
+21
+68
+21
+8
+94
+42
+142
+26
+93
+90
+74
+65
+151
+8
+128
+70
+98
+42
+61
+87
+77
+66
+117
+74
+21
+107
+94
+48
+48
+74
+87
+89
+31
+148
+66
+11
+84
+112
+8
+86
+65
+4
+33
+89
+62
+11
+67
+17
+1
+48
+135
+4
+43
+68
+25
+70
+13
+8
+64
+11
+67
+16
+96
+71
+74
+90
+147
+98
+1
+88
+19
+69
+119
+106
+133
+37
+96
+104
+95
+73
+90
+74
+92
+71
+68
+128
+118
+149
+91
+74
+30
+19
+77
+21
+8
+89
+21
+29
+50
+124
+10
+89
+2
+95
+77
+10
+65
+147
+128
+33
+148
+11
+82
+2
+53
+37
+29
+129
+73
+65
+33
+95
+143
+91
+89
+5
+1
+17
+91
+99
+21
+48
+42
+91
+99
+139
+52
+74
+70
+68
+87
+65
+133
+26
+146
+9
+89
+11
+12
+21
+42
+95
+90
+49
+127
+68
+93
+84
+17
+65
+44
+4
+26
+46
+18
+48
+130
+74
+83
+89
+141
+10
+139
+31
+129
+38
+43
+74
+26
+49
+66
+48
+100
+15
+152
+66
+42
+42
+139
+87
+33
+29
+53
+48
+140
+149
+141
+38
+2
+66
+129
+98
+77
+67
+48
+144
+140
+25
+95
+53
+1
+16
+80
+48
+85
+147
+17
+129
+93
+1
+96
+17
+139
+70
+68
+89
+89
+50
+77
+148
+33
+29
+24
+107
+77
+95
+82
+148
+44
+37
+73
+87
+88
+107
+27
+23
+13
+53
+98
+76
+68
+64
+89
+8
+95
+90
+88
+77
+44
+42
+104
+51
+102
+13
+87
+69
+90
+42
+71
+29
+20
+89
+87
+143
+89
+121
+79
+80
+8
+29
+1
+77
+84
+21
+29
+1
+100
+15
+129
+21
+2
+120
+65
+79
+94
+94
+105
+46
+148
+66
+42
+8
+38
+74
+18
+79
+63
+48
+86
+98
+2
+139
+5
+112
+87
+43
+44
+7
+87
+79
+42
+86
+43
+2
+96
+96
+8
+87
+50
+125
+10
+42
+77
+133
+79
+93
+18
+77
+42
+64
+16
+41
+16
+21
+12
+42
+142
+1
+118
+42
+93
+149
+79
+53
+73
+127
+65
+105
+68
+10
+135
+30
+142
+73
+73
+8
+124
+42
+63
+48
+146
+8
+69
+68
+1
+29
+10
+102
+21
+17
+121
+141
+90
+4
+62
+64
+14
+43
+42
+139
+62
+42
+139
+149
+24
+42
+17
+87
+82
+38
+42
+70
+87
+18
+140
+4
+73
+49
+30
+36
+12
+65
+79
+70
+93
+79
+9
+144
+4
+95
+129
+21
+75
+48
+74
+5
+48
+93
+28
+132
+16
+8
+65
+118
+117
+66
+66
+89
+67
+2
+64
+71
+106
+70
+91
+8
+74
+1
+29
+63
+95
+104
+65
+68
+53
+114
+139
+73
+74
+77
+33
+140
+41
+127
+13
+52
+8
+15
+74
+66
+61
+122
+89
+84
+93
+42
+89
+53
+16
+79
+25
+86
+85
+93
+96
+1
+77
+8
+21
+139
+79
+68
+77
+87
+80
+42
+64
+5
+124
+115
+71
+9
+93
+84
+2
+102
+77
+65
+77
+48
+86
+16
+42
+65
+98
+5
+128
+29
+93
+42
+27
+93
+20
+1
+70
+93
+27
+5
+151
+120
+11
+5
+77
+77
+48
+70
+48
+30
+129
+139
+77
+18
+95
+131
+48
+21
+39
+75
+77
+16
+124
+74
+42
+74
+62
+42
+96
+71
+36
+1
+48
+68
+60
+89
+8
+95
+86
+6
+110
+73
+73
+96
+90
+70
+15
+46
+98
+55
+21
+68
+67
+102
+1
+4
+127
+64
+69
+2
+61
+10
+18
+68
+67
+96
+140
+48
+4
+68
+90
+127
+89
+142
+73
+21
+27
+152
+129
+77
+107
+114
+17
+68
+31
+135
+124
+25
+42
+42
+85
+2
+95
+89
+67
+29
+29
+21
+46
+113
+80
+33
+131
+79
+149
+16
+74
+124
+118
+139
+26
+21
+89
+4
+129
+98
+93
+29
+139
+33
+142
+82
+2
+73
+1
+132
+46
+12
+129
+21
+68
+77
+38
+68
+134
+1
+90
+87
+85
+90
+42
+2
+77
+43
+70
+115
+99
+136
+148
+90
+15
+17
+29
+8
+43
+64
+97
+29
+33
+128
+73
+85
+98
+93
+29
+131
+94
+8
+19
+62
+149
+94
+97
+42
+93
+76
+90
+48
+142
+14
+121
+39
+11
+21
+93
+77
+140
+68
+65
+17
+110
+68
+96
+67
+16
+96
+93
+48
+122
+67
+43
+68
+89
+21
+131
+73
+103
+67
+83
+42
+104
+87
+48
+4
+68
+71
+1
+77
+9
+89
+44
+70
+105
+42
+8
+53
+17
+103
+126
+127
+96
+89
+4
+17
+131
+88
+140
+87
+85
+75
+21
+67
+95
+128
+10
+21
+77
+5
+17
+14
+96
+4
+13
+1
+48
+71
+21
+96
+17
+91
+64
+46
+121
+91
+62
+44
+124
+4
+149
+79
+89
+121
+77
+80
+145
+38
+58
+88
+140
+32
+25
+93
+13
+74
+77
+10
+64
+96
+89
+73
+142
+15
+11
+25
+57
+148
+140
+68
+143
+89
+125
+113
+89
+62
+85
+46
+70
+91
+75
+41
+71
+13
+79
+139
+95
+96
+72
+68
+45
+66
+32
+15
+42
+71
+17
+17
+15
+91
+80
+29
+8
+63
+42
+17
+53
+96
+20
+42
+62
+42
+136
+4
+71
+80
+127
+61
+96
+86
+29
+139
+8
+90
+11
+149
+21
+65
+52
+90
+42
+93
+42
+147
+68
+112
+98
+106
+1
+89
+77
+8
+70
+90
+119
+116
+53
+44
+93
+4
+15
+151
+77
+104
+89
+77
+8
+10
+92
+142
+48
+125
+61
+33
+62
+152
+79
+71
+69
+114
+93
+8
+70
+152
+4
+74
+74
+74
+29
+70
+21
+96
+8
+53
+98
+42
+21
+77
+92
+77
+42
+3
+22
+28
+6
+1
+135
+91
+8
+53
+77
+151
+61
+15
+29
+17
+70
+135
+80
+42
+9
+98
+48
+77
+77
+70
+86
+113
+74
+90
+42
+72
+149
+70
+142
+42
+16
+95
+22
+62
+121
+12
+91
+98
+4
+8
+136
+5
+48
+146
+53
+50
+71
+30
+127
+80
+80
+11
+18
+74
+64
+104
+62
+91
+42
+39
+30
+61
+69
+63
+89
+87
+9
+151
+148
+18
+42
+29
+57
+7
+132
+42
+49
+98
+1
+5
+62
+68
+146
+107
+130
+13
+92
+74
+58
+68
+152
+139
+84
+48
+7
+50
+23
+106
+139
+140
+62
+122
+74
+1
+37
+21
+21
+77
+139
+17
+1
+77
+48
+128
+69
+58
+1
+129
+77
+102
+107
+48
+97
+1
+73
+96
+79
+64
+58
+96
+65
+91
+118
+90
+53
+53
+68
+89
+16
+4
+51
+8
+6
+68
+74
+51
+29
+143
+146
+63
+95
+42
+89
+146
+2
+8
+4
+89
+128
+124
+1
+127
+91
+21
+77
+108
+77
+97
+12
+34
+139
+74
+16
+93
+1
+87
+67
+21
+91
+91
+106
+110
+33
+121
+101
+89
+42
+3
+73
+102
+29
+21
+72
+38
+15
+139
+90
+37
+8
+135
+63
+93
+69
+77
+36
+6
+104
+114
+1
+140
+48
+139
+44
+33
+59
+104
+79
+75
+96
+75
+15
+48
+62
+8
+30
+17
+130
+64
+144
+30
+50
+139
+127
+21
+8
+27
+14
+152
+87
+8
+57
+68
+82
+21
+95
+17
+61
+149
+70
+18
+139
+54
+89
+48
+65
+84
+72
+89
+151
+89
+85
+14
+41
+94
+71
+2
+139
+95
+1
+144
+48
+25
+90
+76
+77
+48
+42
+89
+74
+6
+15
+129
+28
+8
+149
+17
+42
+42
+27
+1
+146
+66
+11
+8
+79
+77
+102
+67
+93
+17
+89
+79
+70
+42
+93
+93
+121
+62
+10
+68
+95
+15
+16
+76
+65
+33
+136
+77
+65
+53
+52
+77
+65
+52
+48
+68
+53
+29
+143
+80
+86
+68
+66
+61
+118
+93
+21
+63
+95
+103
+32
+54
+30
+16
+87
+100
+101
+62
+105
+8
+42
+61
+16
+93
+42
+42
+119
+13
+90
+6
+48
+112
+68
+58
+21
+89
+49
+116
+25
+48
+27
+68
+5
+27
+87
+71
+74
+120
+87
+93
+1
+15
+30
+91
+25
+66
+89
+87
+42
+91
+2
+17
+61
+131
+43
+1
+73
+96
+80
+21
+42
+21
+77
+96
+65
+70
+48
+89
+1
+25
+68
+29
+30
+62
+17
+15
+77
+62
+93
+82
+15
+11
+8
+129
+93
+121
+1
+90
+1
+1
+74
+139
+145
+127
+17
+28
+42
+48
+73
+8
+70
+42
+61
+69
+1
+101
+146
+90
+140
+122
+2
+2
+96
+6
+100
+91
+46
+140
+119
+74
+77
+86
+9
+96
+121
+89
+25
+12
+99
+131
+21
+17
+8
+69
+42
+91
+139
+119
+7
+13
+74
+17
+21
+46
+43
+129
+21
+77
+68
+87
+7
+94
+139
+4
+52
+53
+94
+48
+139
+62
+53
+6
+8
+44
+13
+41
+63
+21
+21
+79
+6
+62
+69
+48
+8
+140
+27
+15
+97
+69
+21
+150
+151
+73
+85
+65
+152
+143
+80
+70
+62
+21
+18
+86
+120
+14
+68
+123
+73
+62
+11
+119
+71
+146
+59
+52
+36
+77
+87
+53
+21
+77
+148
+48
+8
+21
+127
+91
+89
+144
+4
+29
+89
+86
+79
+145
+86
+88
+2
+42
+139
+68
+42
+18
+91
+65
+129
+18
+139
+87
+121
+70
+68
+141
+2
+127
+2
+67
+87
+17
+43
+17
+94
+89
+91
+83
+73
+73
+48
+89
+73
+96
+89
+95
+73
+50
+21
+29
+91
+89
+2
+6
+65
+78
+8
+41
+46
+61
+42
+77
+124
+1
+94
+42
+68
+23
+65
+74
+21
+37
+43
+102
+34
+68
+70
+129
+15
+67
+124
+67
+73
+92
+77
+93
+79
+130
+116
+77
+53
+82
+93
+30
+65
+96
+68
+89
+69
+95
+143
+140
+100
+139
+70
+20
+10
+12
+150
+151
+20
+42
+11
+1
+88
+118
+27
+17
+120
+64
+96
+8
+96
+48
+93
+88
+6
+31
+139
+104
+52
+42
+92
+2
+2
+88
+7
+129
+65
+89
+77
+16
+21
+29
+103
+21
+91
+21
+67
+87
+96
+77
+18
+90
+53
+97
+62
+140
+2
+131
+61
+74
+25
+63
+53
+90
+61
+72
+18
+1
+70
+38
+17
+93
+39
+63
+27
+22
+96
+39
+2
+148
+127
+90
+42
+91
+42
+142
+29
+16
+7
+140
+48
+39
+71
+42
+64
+77
+140
+64
+21
+78
+139
+42
+68
+12
+63
+150
+140
+61
+96
+69
+9
+21
+68
+1
+38
+4
+48
+25
+127
+54
+27
+73
+18
+91
+62
+96
+48
+42
+127
+68
+37
+87
+18
+129
+37
+39
+76
+17
+91
+148
+57
+79
+42
+57
+69
+67
+50
+43
+94
+41
+50
+33
+79
+2
+68
+87
+11
+42
+61
+33
+72
+18
+21
+12
+65
+37
+140
+92
+53
+94
+105
+89
+99
+77
+32
+79
+55
+74
+90
+132
+53
+96
+140
+87
+77
+61
+129
+121
+74
+77
+77
+65
+141
+51
+27
+48
+38
+89
+90
+68
+42
+21
+29
+97
+53
+149
+57
+27
+113
+49
+33
+27
+92
+79
+99
+113
+69
+66
+140
+118
+62
+8
+21
+89
+65
+87
+74
+73
+48
+13
+139
+21
+61
+143
+118
+151
+140
+48
+88
+71
+152
+74
+125
+61
+139
+77
+139
+113
+1
+42
+30
+90
+8
+110
+43
+119
+44
+76
+62
+98
+33
+139
+68
+90
+50
+17
+131
+29
+4
+129
+61
+70
+11
+64
+68
+70
+48
+91
+68
+1
+91
+68
+4
+88
+29
+98
+27
+73
+4
+21
+65
+42
+151
+61
+38
+34
+80
+42
+85
+95
+90
+38
+103
+148
+143
+77
+91
+18
+68
+74
+42
+6
+25
+12
+8
+67
+30
+73
+21
+89
+148
+61
+53
+18
+61
+33
+143
+88
+129
+34
+104
+53
+86
+79
+18
+139
+91
+74
+17
+53
+94
+66
+14
+91
+21
+29
+110
+69
+29
+133
+27
+53
+44
+121
+73
+53
+93
+87
+65
+99
+16
+68
+44
+74
+21
+17
+1
+146
+43
+139
+68
+42
+70
+61
+129
+48
+53
+29
+126
+61
+65
+85
+143
+42
+88
+65
+1
+30
+98
+52
+18
+100
+36
+140
+124
+74
+80
+42
+89
+130
+141
+29
+135
+61
+65
+95
+33
+77
+53
+21
+19
+1
+5
+4
+98
+33
+152
+4
+68
+129
+68
+113
+72
+31
+62
+6
+129
+41
+58
+148
+89
+46
+8
+53
+21
+147
+77
+18
+91
+68
+8
+9
+49
+59
+8
+73
+96
+77
+66
+73
+149
+86
+41
+50
+122
+62
+30
+148
+33
+35
+128
+91
+96
+91
+87
+91
+29
+129
+93
+29
+91
+18
+46
+100
+6
+68
+16
+71
+95
+148
+16
+75
+140
+41
+48
+98
+142
+43
+79
+107
+70
+15
+42
+101
+7
+22
+8
+4
+61
+71
+143
+62
+148
+30
+42
+90
+77
+62
+60
+22
+18
+140
+10
+46
+18
+36
+77
+93
+1
+143
+42
+129
+139
+4
+42
+48
+13
+33
+11
+18
+62
+2
+139
+142
+68
+93
+49
+87
+58
+2
+70
+21
+91
+62
+29
+4
+48
+42
+1
+151
+8
+89
+53
+146
+42
+92
+1
+141
+42
+118
+34
+65
+93
+27
+127
+121
+22
+149
+1
+16
+90
+33
+77
+107
+18
+64
+85
+110
+51
+87
+86
+72
+71
+129
+29
+144
+37
+17
+42
+13
+61
+50
+151
+25
+1
+73
+68
+8
+32
+77
+42
+10
+42
+77
+80
+61
+61
+90
+42
+142
+42
+44
+129
+96
+49
+58
+65
+16
+134
+70
+18
+73
+121
+65
+21
+1
+16
+65
+46
+11
+148
+68
+91
+1
+74
+66
+102
+129
+12
+77
+43
+6
+146
+38
+30
+14
+21
+70
+149
+21
+42
+127
+119
+69
+91
+65
+38
+68
+42
+100
+40
+4
+77
+97
+142
+151
+73
+11
+96
+18
+98
+30
+42
+124
+8
+17
+4
+49
+79
+71
+2
+42
+17
+77
+107
+90
+6
+82
+52
+139
+29
+68
+43
+20
+89
+21
+144
+13
+42
+105
+42
+140
+119
+91
+142
+38
+21
+139
+63
+62
+112
+64
+145
+4
+38
+138
+25
+21
+8
+89
+68
+77
+25
+8
+64
+6
+17
+127
+8
+98
+4
+17
+82
+48
+95
+86
+33
+13
+27
+142
+15
+48
+105
+144
+128
+119
+59
+12
+31
+43
+71
+42
+87
+42
+110
+8
+42
+15
+9
+140
+42
+42
+79
+139
+11
+95
+69
+8
+116
+85
+16
+67
+42
+50
+43
+42
+14
+77
+9
+131
+89
+21
+52
+48
+87
+25
+13
+79
+1
+90
+89
+1
+91
+119
+79
+29
+142
+79
+141
+17
+113
+96
+93
+2
+13
+91
+21
+59
+129
+129
+16
+96
+53
+98
+85
+27
+80
+29
+48
+18
+140
+29
+22
+148
+73
+65
+91
+15
+131
+149
+70
+73
+146
+97
+18
+107
+66
+38
+41
+43
+67
+77
+49
+121
+120
+26
+70
+74
+46
+25
+124
+71
+21
+43
+96
+10
+77
+87
+38
+6
+65
+42
+143
+96
+141
+41
+33
+70
+74
+67
+8
+18
+139
+91
+6
+91
+41
+66
+79
+142
+69
+113
+77
+53
+1
+127
+139
+77
+87
+3
+128
+70
+44
+69
+91
+17
+4
+65
+42
+79
+5
+146
+55
+73
+24
+68
+65
+82
+2
+82
+91
+4
+37
+8
+121
+100
+77
+140
+84
+74
+14
+53
+4
+136
+129
+96
+38
+87
+88
+131
+68
+61
+33
+114
+1
+1
+96
+8
+10
+48
+86
+38
+65
+146
+33
+2
+18
+1
+14
+42
+46
+89
+48
+17
+8
+142
+62
+53
+13
+17
+71
+111
+9
+27
+18
+50
+128
+86
+147
+106
+8
+90
+73
+98
+49
+42
+42
+75
+89
+21
+8
+44
+144
+62
+20
+25
+87
+42
+75
+128
+16
+21
+133
+77
+19
+30
+65
+43
+4
+93
+141
+8
+132
+11
+53
+77
+61
+15
+135
+48
+13
+14
+21
+42
+2
+89
+48
+21
+77
+2
+63
+62
+139
+67
+112
+68
+34
+88
+71
+6
+37
+64
+21
+42
+29
+41
+140
+42
+30
+73
+8
+96
+17
+66
+73
+96
+48
+51
+70
+73
+25
+139
+148
+144
+62
+91
+89
+33
+83
+14
+42
+120
+42
+37
+85
+148
+42
+65
+48
+8
+1
+96
+18
+94
+127
+19
+19
+51
+30
+89
+67
+65
+42
+71
+12
+118
+100
+84
+42
+63
+70
+94
+107
+86
+95
+34
+22
+93
+73
+79
+15
+34
+131
+16
+74
+70
+87
+48
+42
+21
+27
+67
+77
+77
+33
+149
+67
+20
+89
+4
+132
+13
+43
+85
+65
+18
+15
+48
+139
+27
+42
+148
+62
+46
+74
+111
+124
+1
+84
+68
+34
+87
+144
+143
+8
+16
+42
+43
+65
+46
+89
+53
+8
+4
+85
+21
+130
+12
+98
+87
+67
+74
+89
+1
+139
+89
+48
+47
+95
+53
+2
+99
+133
+42
+65
+119
+91
+93
+107
+84
+51
+17
+96
+148
+50
+31
+10
+8
+21
+127
+71
+76
+75
+42
+74
+64
+46
+149
+39
+9
+89
+140
+102
+16
+148
+70
+3
+13
+107
+107
+15
+89
+18
+51
+95
+33
+30
+30
+127
+71
+21
+77
+124
+98
+142
+144
+64
+23
+120
+6
+8
+6
+42
+77
+64
+38
+75
+48
+135
+16
+70
+62
+21
+53
+41
+77
+6
+89
+86
+90
+20
+17
+73
+29
+129
+21
+140
+86
+53
+151
+79
+21
+15
+79
+89
+62
+101
+151
+41
+91
+7
+46
+89
+74
+19
+16
+2
+139
+82
+128
+90
+103
+17
+77
+11
+86
+96
+63
+68
+57
+63
+102
+43
+77
+11
+90
+143
+13
+1
+71
+42
+65
+89
+74
+61
+139
+38
+17
+64
+58
+107
+88
+50
+142
+97
+61
+71
+90
+148
+42
+77
+22
+139
+139
+53
+88
+139
+129
+80
+131
+46
+141
+93
+91
+71
+87
+91
+65
+98
+98
+89
+8
+87
+71
+21
+87
+121
+75
+95
+36
+91
+89
+11
+9
+20
+13
+74
+91
+141
+10
+80
+69
+6
+33
+98
+77
+79
+42
+67
+65
+35
+34
+140
+98
+64
+48
+110
+42
+16
+95
+64
+143
+68
+118
+67
+42
+71
+42
+94
+48
+127
+148
+26
+49
+110
+108
+73
+133
+87
+62
+68
+2
+21
+16
+95
+21
+18
+48
+68
+70
+8
+25
+105
+90
+13
+62
+43
+79
+139
+3
+48
+96
+124
+96
+29
+141
+62
+11
+46
+74
+74
+42
+91
+16
+34
+68
+8
+1
+4
+10
+15
+104
+48
+8
+17
+15
+87
+68
+77
+8
+88
+31
+93
+5
+140
+42
+8
+13
+8
+1
+88
+111
+91
+67
+85
+73
+67
+21
+29
+87
+98
+42
+44
+37
+42
+113
+71
+64
+90
+124
+42
+57
+96
+98
+91
+85
+33
+110
+74
+130
+71
+62
+82
+48
+86
+18
+12
+29
+69
+149
+121
+129
+14
+64
+1
+119
+129
+89
+4
+74
+96
+48
+48
+98
+140
+29
+77
+14
+61
+93
+89
+6
+149
+11
+131
+71
+1
+7
+102
+98
+140
+21
+25
+59
+74
+119
+88
+69
+65
+93
+139
+85
+79
+11
+21
+48
+43
+65
+107
+19
+1
+98
+79
+102
+71
+73
+48
+15
+6
+129
+95
+89
+140
+98
+12
+42
+61
+65
+89
+42
+29
+87
+42
+139
+95
+96
+74
+21
+70
+70
+1
+67
+68
+77
+21
+26
+68
+50
+86
+71
+29
+142
+68
+33
+105
+21
+67
+86
+1
+52
+53
+17
+61
+91
+17
+80
+49
+42
+148
+72
+21
+16
+46
+142
+140
+26
+89
+17
+11
+85
+33
+96
+148
+16
+65
+10
+93
+42
+31
+57
+105
+76
+146
+43
+91
+1
+127
+4
+69
+67
+70
+70
+79
+90
+27
+29
+8
+62
+51
+119
+105
+89
+48
+42
+70
+119
+21
+149
+68
+8
+70
+89
+77
+63
+64
+16
+2
+99
+86
+46
+26
+91
+29
+73
+65
+15
+17
+74
+77
+33
+127
+24
+11
+96
+98
+143
+53
+62
+140
+91
+2
+48
+65
+89
+12
+54
+29
+42
+129
+93
+61
+46
+42
+42
+104
+83
+4
+48
+2
+42
+53
+19
+106
+66
+50
+80
+15
+66
+86
+48
+94
+17
+140
+25
+57
+8
+30
+74
+48
+42
+98
+81
+21
+110
+21
+21
+63
+42
+100
+21
+87
+13
+53
+29
+43
+20
+21
+63
+27
+98
+59
+75
+113
+15
+62
+24
+16
+90
+27
+94
+84
+8
+129
+8
+94
+20
+7
+20
+21
+114
+73
+71
+63
+73
+120
+100
+42
+91
+12
+6
+14
+148
+34
+1
+8
+54
+42
+127
+30
+91
+95
+115
+12
+95
+17
+18
+53
+8
+42
+48
+30
+65
+43
+68
+80
+34
+42
+42
+91
+29
+70
+16
+17
+48
+59
+7
+73
+1
+93
+91
+90
+65
+88
+95
+140
+70
+21
+129
+130
+11
+71
+58
+124
+89
+21
+8
+84
+89
+66
+10
+91
+37
+53
+77
+30
+148
+14
+65
+90
+48
+42
+93
+61
+68
+95
+93
+48
+69
+89
+73
+32
+76
+21
+147
+124
+48
+46
+14
+42
+2
+21
+53
+89
+18
+90
+48
+61
+71
+53
+67
+17
+74
+66
+68
+96
+140
+75
+93
+87
+140
+8
+72
+67
+46
+65
+17
+27
+89
+74
+8
+13
+44
+13
+2
+17
+51
+93
+48
+20
+68
+129
+21
+85
+89
+48
+65
+95
+93
+124
+79
+11
+42
+114
+98
+68
+62
+21
+77
+104
+33
+8
+68
+105
+65
+65
+8
+77
+65
+86
+131
+86
+42
+10
+51
+29
+77
+8
+61
+66
+71
+91
+94
+140
+129
+72
+61
+87
+38
+64
+14
+104
+21
+80
+25
+48
+38
+91
+48
+96
+132
+68
+77
+41
+98
+1
+73
+27
+139
+68
+65
+106
+96
+43
+93
+146
+100
+129
+64
+21
+66
+62
+42
+10
+89
+21
+107
+16
+44
+110
+70
+17
+65
+4
+14
+98
+74
+33
+91
+96
+21
+16
+65
+14
+2
+64
+65
+17
+73
+77
+139
+89
+74
+118
+134
+29
+30
+48
+88
+125
+75
+62
+48
+64
+151
+43
+43
+91
+74
+15
+121
+71
+73
+1
+42
+112
+4
+69
+120
+89
+8
+69
+68
+42
+1
+62
+46
+21
+15
+51
+89
+25
+8
+149
+62
+38
+65
+71
+74
+21
+89
+131
+135
+21
+129
+89
+77
+23
+65
+10
+118
+88
+71
+58
+42
+9
+95
+42
+98
+129
+134
+2
+12
+31
+84
+52
+66
+12
+139
+33
+21
+105
+2
+46
+67
+18
+74
+48
+23
+68
+15
+87
+139
+4
+69
+30
+97
+98
+43
+84
+93
+68
+38
+42
+99
+77
+113
+20
+8
+65
+88
+18
+41
+104
+27
+8
+73
+65
+1
+98
+68
+85
+98
+21
+49
+6
+2
+21
+101
+25
+58
+129
+17
+129
+15
+48
+42
+59
+150
+62
+10
+143
+143
+68
+16
+1
+149
+30
+89
+21
+122
+27
+93
+96
+38
+127
+33
+69
+143
+91
+6
+90
+1
+70
+109
+48
+91
+116
+69
+21
+7
+44
+129
+129
+29
+121
+4
+6
+89
+67
+48
+52
+146
+1
+33
+42
+62
+128
+65
+13
+148
+10
+68
+96
+85
+87
+84
+77
+90
+26
+41
+87
+55
+95
+59
+48
+67
+42
+67
+86
+62
+113
+139
+139
+69
+48
+62
+5
+98
+134
+67
+13
+65
+30
+70
+73
+48
+145
+87
+91
+71
+8
+53
+66
+120
+10
+89
+105
+148
+124
+61
+2
+30
+87
+51
+98
+93
+62
+27
+77
+77
+149
+66
+62
+18
+21
+15
+13
+27
+72
+95
+147
+64
+100
+70
+43
+53
+90
+129
+125
+77
+139
+74
+67
+77
+90
+139
+52
+69
+61
+91
+42
+39
+18
+88
+79
+61
+129
+139
+146
+48
+48
+6
+95
+88
+139
+73
+69
+2
+64
+86
+21
+89
+42
+95
+99
+64
+70
+66
+140
+15
+31
+42
+124
+14
+105
+30
+29
+91
+9
+85
+21
+125
+70
+66
+59
+19
+38
+91
+149
+62
+43
+70
+31
+46
+65
+68
+53
+149
+16
+140
+6
+31
+91
+88
+65
+86
+81
+59
+42
+70
+33
+77
+21
+128
+8
+142
+21
+70
+96
+46
+96
+62
+146
+96
+89
+48
+42
+104
+65
+91
+13
+144
+19
+73
+21
+94
+139
+89
+97
+70
+71
+17
+6
+30
+48
+121
+61
+17
+38
+21
+18
+121
+14
+145
+91
+66
+33
+121
+77
+147
+71
+91
+33
+53
+80
+42
+143
+48
+48
+95
+77
+103
+127
+2
+85
+15
+19
+6
+129
+69
+1
+15
+17
+139
+11
+95
+128
+86
+91
+61
+61
+69
+8
+143
+73
+48
+96
+73
+26
+29
+19
+68
+33
+67
+48
+141
+79
+88
+107
+77
+139
+140
+89
+42
+53
+2
+48
+8
+97
+21
+77
+38
+103
+45
+48
+6
+96
+96
+149
+88
+43
+93
+79
+43
+90
+8
+74
+120
+140
+57
+1
+79
+69
+15
+53
+88
+68
+68
+27
+96
+17
+69
+10
+6
+25
+27
+140
+2
+101
+3
+148
+61
+146
+65
+52
+64
+134
+73
+33
+89
+140
+65
+1
+42
+68
+144
+140
+1
+86
+77
+124
+21
+48
+53
+16
+42
+2
+4
+77
+9
+74
+65
+44
+42
+17
+11
+93
+91
+1
+74
+58
+52
+82
+33
+128
+27
+121
+21
+42
+142
+2
+139
+74
+104
+121
+127
+48
+27
+21
+65
+96
+86
+71
+74
+105
+61
+46
+8
+91
+95
+89
+26
+63
+9
+48
+64
+101
+84
+52
+12
+53
+74
+97
+118
+144
+129
+62
+48
+139
+70
+87
+48
+77
+12
+65
+26
+96
+127
+74
+8
+147
+69
+74
+118
+25
+33
+42
+21
+14
+139
+82
+80
+61
+59
+142
+90
+93
+81
+92
+1
+11
+135
+15
+48
+146
+127
+5
+86
+86
+8
+77
+104
+91
+42
+21
+27
+151
+148
+140
+71
+75
+27
+21
+26
+77
+7
+29
+139
+96
+93
+85
+65
+43
+95
+62
+11
+5
+18
+97
+98
+14
+65
+9
+26
+8
+11
+33
+85
+68
+129
+22
+61
+132
+15
+96
+21
+8
+15
+59
+77
+107
+15
+78
+67
+6
+17
+71
+129
+101
+7
+1
+146
+42
+141
+15
+27
+86
+4
+48
+90
+73
+64
+42
+48
+77
+21
+8
+50
+43
+48
+142
+1
+42
+69
+79
+49
+15
+49
+127
+121
+21
+18
+77
+73
+148
+148
+37
+21
+64
+62
+16
+8
+71
+48
+74
+1
+73
+43
+77
+95
+140
+139
+69
+133
+129
+42
+29
+1
+89
+88
+79
+27
+95
+77
+64
+13
+80
+78
+76
+38
+42
+129
+124
+48
+1
+121
+37
+143
+64
+77
+89
+89
+91
+68
+70
+21
+77
+22
+148
+77
+48
+88
+149
+86
+2
+85
+95
+42
+89
+65
+11
+48
+25
+140
+69
+77
+48
+89
+112
+74
+12
+65
+29
+51
+31
+77
+14
+104
+77
+61
+77
+42
+2
+41
+95
+68
+52
+107
+8
+139
+42
+87
+93
+93
+71
+2
+77
+76
+42
+21
+74
+69
+18
+71
+64
+149
+139
+17
+30
+29
+56
+13
+8
+14
+8
+69
+74
+71
+90
+59
+64
+89
+89
+48
+8
+89
+139
+49
+145
+107
+134
+93
+8
+42
+2
+42
+95
+89
+25
+134
+94
+48
+148
+146
+12
+149
+127
+149
+42
+42
+118
+61
+62
+21
+142
+98
+53
+42
+42
+95
+77
+48
+91
+65
+87
+1
+56
+87
+13
+21
+37
+46
+18
+141
+98
+96
+56
+73
+43
+93
+16
+51
+77
+129
+146
+67
+16
+79
+18
+90
+84
+18
+48
+121
+31
+29
+15
+41
+53
+13
+92
+8
+91
+65
+48
+107
+87
+4
+94
+8
+6
+90
+8
+144
+74
+86
+46
+89
+73
+147
+129
+65
+38
+1
+70
+144
+130
+140
+48
+89
+59
+135
+21
+67
+77
+42
+91
+29
+149
+76
+129
+77
+91
+6
+82
+17
+11
+42
+121
+11
+98
+14
+4
+128
+29
+1
+32
+80
+145
+80
+77
+27
+8
+77
+80
+17
+63
+53
+129
+29
+46
+50
+15
+21
+17
+151
+38
+16
+70
+25
+70
+129
+151
+42
+89
+77
+6
+68
+16
+2
+15
+144
+122
+91
+15
+70
+10
+27
+46
+70
+90
+1
+14
+79
+31
+63
+77
+17
+42
+105
+16
+48
+17
+24
+109
+70
+38
+71
+106
+54
+61
+140
+62
+93
+42
+4
+105
+91
+101
+42
+19
+42
+2
+15
+46
+48
+11
+121
+112
+104
+10
+13
+21
+65
+94
+93
+4
+30
+6
+129
+21
+98
+90
+43
+62
+98
+2
+128
+140
+73
+127
+91
+42
+144
+32
+100
+130
+61
+66
+93
+43
+15
+16
+79
+50
+25
+21
+27
+29
+89
+25
+2
+108
+119
+66
+86
+89
+16
+68
+62
+53
+4
+91
+18
+21
+80
+107
+149
+131
+8
+79
+29
+62
+42
+152
+43
+84
+91
+65
+75
+62
+125
+62
+62
+7
+49
+29
+63
+21
+42
+75
+73
+65
+142
+1
+98
+125
+82
+89
+7
+29
+13
+54
+52
+21
+107
+26
+1
+77
+73
+89
+2
+53
+30
+42
+16
+1
+89
+107
+65
+42
+8
+33
+27
+65
+85
+44
+1
+46
+22
+21
+78
+42
+74
+124
+129
+12
+48
+21
+27
+29
+146
+73
+76
+89
+89
+1
+80
+27
+10
+64
+79
+129
+66
+29
+142
+22
+129
+12
+38
+30
+95
+88
+16
+8
+89
+79
+15
+15
+42
+125
+43
+53
+10
+136
+68
+1
+140
+133
+6
+23
+1
+29
+33
+89
+96
+42
+68
+48
+77
+19
+5
+11
+7
+113
+12
+105
+8
+89
+9
+6
+140
+53
+65
+107
+29
+7
+38
+52
+120
+42
+16
+75
+72
+27
+146
+149
+37
+52
+77
+42
+42
+100
+147
+77
+95
+95
+103
+91
+31
+31
+96
+68
+25
+90
+16
+29
+27
+42
+42
+12
+41
+75
+129
+64
+89
+77
+21
+53
+68
+33
+74
+24
+67
+98
+64
+29
+77
+48
+30
+67
+68
+105
+21
+27
+1
+2
+96
+35
+80
+96
+41
+74
+107
+65
+62
+82
+1
+77
+80
+38
+62
+90
+71
+24
+16
+22
+50
+93
+79
+75
+17
+89
+21
+96
+49
+137
+140
+91
+96
+96
+92
+4
+1
+2
+89
+42
+79
+48
+69
+103
+6
+59
+140
+90
+78
+74
+16
+135
+86
+96
+143
+149
+77
+1
+87
+139
+6
+96
+53
+70
+48
+87
+93
+96
+12
+61
+25
+75
+38
+17
+4
+26
+3
+11
+101
+149
+68
+16
+90
+142
+85
+149
+53
+47
+69
+4
+8
+124
+96
+129
+129
+87
+73
+68
+96
+42
+65
+89
+14
+65
+65
+19
+124
+10
+48
+89
+149
+129
+69
+52
+79
+42
+86
+14
+9
+13
+86
+129
+13
+91
+1
+65
+85
+121
+65
+75
+14
+21
+1
+17
+46
+70
+79
+55
+53
+139
+68
+69
+42
+145
+21
+140
+84
+12
+61
+95
+17
+1
+140
+144
+5
+96
+87
+69
+22
+11
+17
+50
+14
+48
+1
+79
+127
+2
+42
+75
+61
+48
+11
+6
+88
+71
+4
+93
+68
+97
+135
+42
+30
+22
+39
+11
+71
+79
+24
+89
+16
+89
+149
+17
+53
+121
+91
+8
+29
+125
+131
+8
+59
+89
+6
+73
+20
+142
+108
+33
+63
+8
+114
+77
+112
+139
+8
+148
+102
+15
+95
+61
+86
+64
+4
+73
+99
+48
+140
+43
+127
+61
+12
+48
+119
+121
+133
+130
+77
+7
+20
+73
+39
+90
+93
+29
+4
+117
+66
+43
+42
+121
+128
+65
+64
+29
+66
+140
+89
+89
+65
+98
+98
+68
+71
+140
+2
+130
+48
+51
+16
+42
+48
+36
+43
+71
+126
+69
+75
+38
+96
+98
+50
+15
+100
+70
+95
+10
+91
+1
+147
+148
+86
+77
+104
+38
+38
+88
+66
+8
+33
+71
+71
+9
+114
+18
+91
+27
+4
+73
+90
+70
+73
+124
+80
+89
+68
+77
+77
+30
+42
+21
+24
+21
+38
+39
+112
+146
+121
+97
+68
+11
+27
+29
+96
+129
+27
+87
+98
+89
+86
+90
+29
+38
+67
+71
+97
+21
+140
+37
+27
+21
+26
+142
+89
+6
+48
+91
+2
+69
+124
+21
+9
+68
+37
+86
+48
+73
+2
+69
+6
+56
+89
+18
+75
+114
+79
+43
+98
+1
+51
+4
+15
+1
+44
+89
+121
+89
+52
+85
+27
+80
+148
+103
+29
+89
+89
+25
+128
+69
+42
+70
+71
+142
+94
+19
+37
+71
+17
+48
+95
+62
+112
+29
+48
+46
+42
+93
+74
+43
+93
+84
+142
+127
+113
+65
+129
+70
+4
+50
+80
+3
+129
+140
+77
+2
+20
+148
+31
+77
+77
+120
+65
+146
+13
+125
+65
+91
+68
+68
+48
+90
+52
+25
+140
+89
+93
+7
+2
+87
+29
+72
+77
+91
+148
+147
+8
+149
+42
+42
+11
+84
+14
+70
+13
+14
+30
+17
+91
+42
+88
+21
+90
+142
+86
+86
+25
+29
+27
+91
+129
+74
+77
+98
+71
+7
+121
+43
+2
+88
+50
+80
+121
+93
+51
+63
+77
+14
+48
+6
+68
+42
+52
+52
+68
+43
+8
+30
+2
+7
+13
+91
+27
+124
+64
+29
+59
+78
+77
+65
+96
+1
+89
+2
+12
+68
+91
+145
+80
+146
+86
+7
+17
+48
+30
+142
+1
+16
+8
+1
+48
+12
+48
+14
+46
+69
+1
+89
+103
+25
+65
+8
+98
+53
+130
+65
+64
+73
+15
+69
+140
+42
+1
+15
+98
+95
+15
+90
+56
+69
+41
+74
+77
+15
+94
+8
+27
+128
+48
+77
+77
+129
+98
+29
+89
+89
+85
+29
+4
+140
+8
+89
+14
+42
+149
+91
+27
+87
+146
+86
+96
+77
+99
+77
+61
+1
+87
+48
+105
+42
+17
+77
+1
+119
+121
+98
+13
+107
+28
+22
+17
+89
+70
+140
+5
+144
+21
+68
+42
+93
+21
+65
+121
+77
+62
+94
+73
+134
+70
+52
+17
+68
+141
+66
+8
+79
+140
+89
+8
+13
+41
+44
+140
+43
+89
+91
+61
+68
+21
+63
+15
+11
+95
+6
+89
+84
+70
+128
+42
+139
+10
+89
+104
+48
+8
+88
+73
+148
+4
+29
+29
+48
+129
+96
+96
+79
+48
+20
+42
+85
+129
+110
+8
+21
+48
+73
+8
+62
+67
+48
+20
+135
+38
+15
+6
+48
+25
+140
+42
+42
+2
+11
+116
+132
+129
+10
+21
+96
+75
+79
+46
+46
+48
+87
+2
+68
+4
+128
+63
+95
+144
+68
+13
+21
+113
+91
+121
+61
+7
+85
+91
+4
+29
+52
+96
+5
+15
+149
+4
+77
+62
+50
+88
+133
+93
+73
+42
+30
+59
+96
+66
+73
+77
+43
+7
+79
+21
+140
+8
+18
+42
+27
+79
+21
+48
+44
+30
+2
+107
+147
+107
+77
+39
+95
+72
+77
+145
+48
+89
+1
+39
+149
+1
+68
+77
+114
+75
+131
+73
+7
+81
+39
+73
+77
+57
+98
+89
+25
+2
+91
+26
+30
+42
+70
+140
+143
+140
+77
+88
+139
+17
+34
+130
+86
+8
+10
+74
+77
+121
+75
+77
+48
+42
+87
+33
+144
+29
+149
+6
+107
+129
+32
+79
+6
+41
+8
+53
+141
+42
+64
+129
+4
+13
+11
+141
+4
+42
+77
+96
+60
+57
+149
+90
+91
+69
+76
+94
+27
+98
+48
+42
+69
+95
+16
+39
+39
+29
+6
+63
+43
+18
+2
+25
+75
+4
+67
+74
+71
+16
+21
+17
+140
+71
+62
+29
+48
+27
+89
+51
+15
+148
+1
+64
+48
+75
+97
+88
+33
+21
+77
+2
+68
+92
+95
+131
+143
+69
+121
+105
+13
+148
+48
+129
+128
+103
+4
+121
+65
+17
+14
+124
+140
+67
+68
+85
+70
+66
+21
+41
+65
+96
+48
+89
+21
+79
+74
+38
+73
+90
+89
+42
+39
+68
+27
+100
+8
+42
+43
+7
+89
+131
+27
+7
+146
+17
+42
+33
+74
+148
+1
+129
+5
+122
+23
+144
+11
+147
+30
+4
+87
+35
+8
+129
+10
+106
+42
+67
+105
+95
+75
+131
+104
+93
+77
+30
+38
+139
+26
+71
+39
+7
+114
+97
+58
+77
+66
+1
+30
+93
+21
+77
+117
+95
+90
+140
+79
+17
+29
+2
+79
+95
+122
+12
+91
+113
+140
+91
+3
+21
+91
+56
+149
+115
+67
+65
+144
+85
+21
+18
+85
+42
+48
+137
+87
+1
+139
+21
+50
+152
+96
+50
+1
+100
+21
+27
+89
+65
+71
+27
+29
+53
+48
+33
+139
+148
+89
+4
+122
+102
+101
+62
+144
+77
+6
+62
+7
+33
+61
+143
+59
+89
+42
+70
+21
+68
+124
+33
+79
+70
+21
+8
+15
+21
+149
+15
+80
+17
+141
+104
+6
+115
+37
+71
+87
+1
+107
+38
+42
+94
+13
+96
+142
+95
+48
+120
+17
+75
+18
+50
+2
+143
+64
+48
+8
+6
+8
+77
+62
+21
+17
+4
+33
+82
+61
+14
+96
+67
+77
+86
+48
+74
+87
+96
+127
+90
+149
+53
+131
+142
+129
+80
+92
+71
+140
+65
+89
+10
+93
+15
+91
+20
+95
+33
+42
+46
+94
+64
+89
+87
+127
+48
+8
+70
+77
+140
+29
+29
+65
+91
+7
+87
+30
+29
+106
+95
+69
+8
+76
+150
+6
+68
+42
+87
+29
+56
+17
+62
+94
+143
+53
+68
+6
+120
+75
+19
+127
+75
+62
+4
+70
+8
+63
+29
+46
+9
+129
+42
+77
+52
+4
+1
+80
+33
+87
+51
+15
+74
+4
+73
+21
+87
+77
+112
+77
+127
+122
+30
+8
+1
+133
+29
+61
+88
+8
+73
+22
+27
+86
+21
+30
+95
+80
+91
+42
+42
+65
+130
+12
+21
+121
+46
+1
+48
+1
+79
+42
+141
+87
+28
+64
+75
+42
+74
+91
+16
+127
+91
+48
+78
+89
+27
+71
+42
+10
+94
+65
+31
+8
+80
+73
+69
+9
+79
+56
+18
+16
+13
+104
+69
+10
+38
+2
+29
+77
+62
+74
+1
+65
+8
+77
+65
+91
+42
+105
+77
+114
+50
+130
+80
+4
+61
+17
+74
+151
+8
+42
+42
+107
+96
+2
+29
+46
+95
+124
+74
+70
+134
+91
+2
+79
+13
+67
+53
+95
+11
+118
+83
+139
+86
+15
+19
+73
+21
+8
+143
+14
+54
+80
+84
+89
+108
+140
+37
+79
+42
+8
+4
+1
+65
+91
+68
+113
+42
+77
+42
+70
+74
+42
+89
+104
+21
+93
+74
+74
+4
+57
+25
+70
+90
+12
+2
+90
+8
+23
+68
+127
+1
+130
+4
+135
+105
+34
+87
+72
+90
+89
+49
+91
+96
+16
+8
+75
+86
+65
+27
+23
+48
+5
+77
+140
+1
+80
+127
+16
+15
+129
+79
+67
+88
+48
+95
+17
+25
+98
+91
+93
+1
+88
+15
+94
+2
+142
+77
+33
+91
+74
+121
+61
+8
+119
+96
+127
+13
+2
+13
+82
+73
+41
+90
+41
+64
+62
+91
+13
+61
+70
+86
+77
+15
+76
+113
+15
+73
+69
+48
+107
+97
+77
+151
+43
+86
+73
+68
+48
+71
+62
+64
+48
+121
+53
+88
+129
+96
+98
+22
+104
+73
+24
+129
+96
+8
+52
+33
+61
+135
+142
+88
+127
+70
+89
+48
+1
+42
+49
+131
+60
+100
+21
+42
+84
+25
+21
+129
+8
+85
+37
+148
+73
+141
+142
+15
+8
+64
+63
+70
+101
+46
+148
+70
+25
+93
+65
+45
+73
+80
+106
+64
+88
+6
+85
+46
+96
+128
+38
+1
+74
+90
+21
+42
+114
+61
+140
+96
+25
+8
+96
+1
+121
+48
+140
+87
+65
+124
+46
+85
+134
+65
+42
+140
+134
+23
+67
+34
+129
+89
+72
+13
+1
+1
+62
+87
+77
+89
+87
+6
+17
+126
+15
+21
+77
+21
+67
+16
+140
+21
+140
+43
+88
+77
+20
+42
+18
+98
+96
+42
+8
+4
+96
+1
+21
+29
+62
+140
+20
+48
+140
+87
+90
+2
+18
+6
+139
+53
+15
+24
+21
+11
+27
+65
+7
+29
+37
+134
+41
+139
+2
+48
+90
+79
+16
+85
+98
+66
+93
+53
+15
+9
+49
+66
+21
+16
+127
+8
+34
+65
+39
+152
+13
+27
+52
+8
+107
+76
+79
+102
+98
+27
+100
+64
+121
+1
+105
+124
+87
+67
+62
+77
+13
+89
+77
+16
+33
+53
+67
+77
+84
+77
+80
+89
+42
+63
+86
+22
+46
+84
+82
+13
+124
+18
+148
+134
+65
+71
+43
+69
+89
+21
+69
+83
+89
+61
+87
+12
+56
+6
+18
+139
+69
+142
+125
+129
+77
+38
+14
+29
+80
+16
+48
+79
+53
+148
+68
+48
+21
+91
+68
+68
+132
+77
+91
+69
+53
+77
+15
+14
+66
+61
+88
+119
+62
+21
+79
+136
+1
+15
+52
+89
+48
+10
+2
+140
+74
+59
+48
+74
+4
+87
+90
+18
+96
+70
+43
+85
+1
+33
+42
+120
+68
+25
+21
+60
+46
+63
+42
+146
+87
+98
+71
+6
+150
+148
+27
+7
+17
+68
+68
+90
+112
+129
+10
+87
+151
+143
+107
+51
+129
+6
+62
+69
+133
+21
+89
+139
+42
+140
+89
+17
+93
+146
+68
+13
+86
+47
+64
+21
+65
+21
+1
+30
+67
+92
+89
+99
+53
+79
+68
+48
+75
+42
+62
+17
+140
+79
+8
+8
+18
+124
+42
+59
+147
+118
+144
+9
+50
+93
+109
+68
+51
+148
+11
+24
+21
+42
+106
+9
+15
+11
+77
+8
+74
+54
+96
+127
+79
+6
+41
+42
+23
+8
+77
+67
+77
+4
+1
+77
+149
+96
+16
+95
+104
+100
+46
+90
+124
+55
+8
+42
+18
+141
+75
+17
+107
+98
+124
+134
+80
+1
+52
+65
+77
+87
+73
+121
+87
+91
+42
+53
+85
+89
+97
+1
+89
+131
+42
+42
+96
+41
+118
+43
+2
+67
+11
+17
+48
+3
+88
+85
+8
+5
+89
+123
+74
+98
+2
+71
+54
+116
+5
+45
+5
+114
+3
+139
+68
+67
+11
+80
+11
+21
+143
+68
+74
+73
+42
+14
+27
+102
+9
+139
+108
+89
+74
+136
+30
+66
+120
+42
+87
+38
+70
+8
+110
+149
+48
+79
+91
+53
+136
+48
+1
+89
+17
+71
+15
+15
+74
+93
+53
+100
+13
+41
+95
+49
+21
+38
+8
+85
+2
+93
+129
+73
+15
+42
+59
+50
+90
+77
+79
+91
+95
+8
+42
+139
+8
+148
+89
+34
+77
+69
+76
+77
+130
+139
+82
+51
+148
+86
+70
+59
+26
+77
+42
+38
+42
+129
+91
+46
+65
+21
+129
+129
+46
+67
+67
+69
+17
+87
+48
+131
+121
+13
+8
+89
+65
+41
+117
+114
+29
+70
+15
+146
+129
+52
+96
+27
+86
+27
+141
+139
+27
+93
+77
+89
+64
+23
+62
+21
+48
+130
+68
+129
+77
+41
+98
+53
+74
+71
+60
+38
+26
+69
+42
+127
+107
+33
+15
+61
+129
+98
+59
+43
+30
+93
+129
+21
+53
+18
+42
+144
+4
+77
+94
+132
+21
+80
+64
+74
+65
+85
+69
+95
+74
+89
+46
+68
+107
+59
+96
+69
+129
+98
+65
+73
+35
+21
+6
+16
+41
+139
+139
+72
+138
+16
+100
+68
+27
+77
+16
+119
+152
+57
+140
+21
+107
+27
+18
+73
+69
+23
+8
+74
+12
+37
+65
+21
+68
+27
+77
+43
+139
+77
+62
+1
+75
+62
+21
+129
+21
+30
+89
+67
+146
+89
+69
+89
+17
+77
+17
+139
+14
+114
+124
+48
+53
+8
+32
+67
+108
+135
+77
+21
+30
+42
+15
+62
+140
+44
+99
+95
+11
+77
+14
+37
+91
+68
+30
+89
+1
+129
+21
+65
+42
+27
+139
+8
+70
+89
+37
+82
+62
+90
+68
+10
+71
+56
+91
+62
+1
+91
+140
+77
+140
+25
+8
+17
+59
+93
+74
+37
+148
+34
+143
+42
+89
+43
+91
+1
+8
+54
+103
+38
+64
+12
+18
+119
+79
+89
+64
+79
+4
+15
+70
+91
+77
+31
+90
+42
+59
+21
+8
+48
+65
+144
+21
+142
+70
+132
+129
+148
+91
+21
+53
+38
+4
+33
+141
+86
+89
+53
+148
+68
+37
+107
+31
+65
+77
+139
+142
+75
+70
+21
+93
+75
+93
+42
+15
+96
+62
+70
+144
+48
+29
+63
+124
+64
+26
+42
+18
+67
+8
+139
+117
+11
+33
+17
+77
+147
+13
+90
+21
+25
+139
+16
+73
+139
+90
+103
+91
+118
+70
+21
+9
+74
+18
+77
+7
+48
+77
+8
+70
+63
+29
+146
+94
+25
+129
+148
+14
+104
+25
+29
+148
+129
+130
+69
+23
+74
+74
+33
+13
+77
+53
+87
+29
+91
+51
+95
+21
+52
+96
+2
+13
+26
+72
+96
+129
+90
+1
+89
+27
+68
+21
+98
+96
+85
+64
+149
+8
+134
+89
+98
+89
+4
+87
+33
+8
+6
+8
+42
+79
+73
+121
+89
+100
+18
+73
+97
+71
+142
+8
+90
+9
+140
+48
+31
+19
+95
+42
+129
+17
+43
+149
+27
+75
+89
+65
+34
+66
+134
+142
+64
+48
+13
+77
+96
+35
+68
+107
+42
+150
+93
+1
+113
+21
+96
+100
+127
+53
+21
+53
+140
+2
+61
+107
+139
+1
+21
+33
+53
+1
+116
+93
+6
+21
+21
+8
+90
+86
+17
+89
+31
+95
+5
+85
+79
+73
+15
+148
+2
+18
+77
+29
+96
+15
+21
+77
+27
+149
+28
+1
+146
+37
+95
+27
+18
+4
+71
+63
+21
+90
+131
+85
+38
+91
+20
+77
+2
+96
+91
+140
+18
+115
+17
+46
+134
+87
+70
+42
+65
+33
+42
+31
+139
+17
+68
+90
+105
+65
+77
+29
+75
+95
+89
+27
+48
+77
+15
+124
+124
+70
+52
+61
+73
+124
+10
+58
+65
+5
+77
+70
+129
+111
+33
+91
+135
+140
+141
+46
+42
+54
+84
+8
+42
+89
+77
+89
+48
+37
+18
+14
+53
+140
+21
+22
+143
+48
+15
+4
+48
+72
+18
+89
+43
+65
+149
+42
+42
+38
+48
+77
+64
+68
+12
+142
+79
+135
+96
+82
+33
+90
+14
+77
+86
+37
+149
+42
+50
+24
+10
+16
+25
+62
+93
+70
+96
+13
+48
+69
+70
+25
+148
+48
+128
+68
+48
+24
+48
+68
+13
+74
+59
+40
+81
+74
+65
+48
+124
+69
+48
+67
+7
+151
+83
+68
+96
+69
+107
+29
+71
+21
+71
+48
+142
+50
+64
+46
+130
+107
+1
+102
+11
+42
+64
+37
+143
+67
+62
+144
+79
+25
+68
+6
+140
+74
+151
+89
+90
+9
+121
+85
+65
+8
+79
+47
+62
+38
+18
+94
+5
+8
+30
+16
+121
+42
+86
+96
+73
+86
+71
+38
+21
+83
+18
+140
+18
+3
+70
+49
+74
+2
+1
+2
+29
+4
+139
+2
+140
+139
+131
+7
+77
+6
+127
+51
+130
+134
+96
+74
+138
+68
+16
+134
+120
+139
+14
+89
+120
+89
+148
+75
+29
+21
+64
+61
+5
+44
+139
+90
+66
+4
+70
+67
+94
+89
+48
+21
+91
+4
+95
+42
+42
+69
+77
+85
+46
+129
+9
+4
+74
+48
+90
+63
+14
+18
+41
+77
+1
+10
+74
+16
+29
+65
+50
+17
+63
+142
+146
+42
+90
+77
+85
+77
+30
+68
+89
+8
+91
+140
+67
+130
+38
+8
+127
+89
+74
+149
+146
+77
+62
+129
+129
+85
+113
+113
+116
+73
+139
+69
+127
+18
+146
+66
+88
+43
+1
+53
+33
+42
+98
+87
+52
+113
+15
+114
+88
+54
+111
+98
+18
+6
+42
+77
+79
+27
+95
+42
+48
+10
+31
+98
+132
+102
+42
+131
+21
+38
+15
+21
+29
+21
+89
+127
+39
+38
+6
+31
+8
+31
+21
+127
+16
+11
+6
+95
+91
+74
+8
+139
+42
+14
+74
+27
+33
+90
+42
+53
+77
+43
+143
+68
+19
+98
+69
+18
+13
+5
+8
+73
+4
+68
+33
+70
+13
+90
+93
+10
+62
+116
+96
+11
+59
+77
+1
+77
+72
+106
+62
+61
+146
+124
+95
+17
+70
+17
+65
+93
+64
+21
+74
+69
+142
+70
+134
+114
+90
+79
+1
+44
+27
+61
+69
+70
+46
+67
+14
+93
+27
+8
+18
+84
+9
+74
+42
+48
+67
+68
+105
+88
+49
+128
+43
+88
+18
+85
+121
+38
+43
+46
+4
+74
+15
+86
+21
+77
+8
+65
+16
+33
+90
+104
+77
+80
+64
+91
+67
+89
+15
+86
+50
+114
+70
+61
+22
+14
+66
+104
+1
+14
+77
+140
+33
+121
+97
+48
+70
+43
+10
+139
+18
+62
+111
+41
+149
+77
+13
+46
+17
+77
+21
+69
+124
+93
+149
+22
+30
+148
+30
+129
+73
+17
+127
+8
+72
+37
+10
+8
+89
+21
+48
+87
+148
+26
+69
+140
+74
+93
+42
+74
+135
+146
+1
+62
+96
+70
+16
+29
+111
+18
+66
+124
+32
+20
+94
+88
+89
+142
+144
+146
+48
+72
+30
+48
+64
+2
+142
+147
+89
+13
+89
+69
+87
+70
+38
+6
+4
+42
+127
+48
+2
+18
+37
+21
+65
+66
+68
+93
+113
+42
+1
+84
+1
+18
+14
+42
+85
+42
+16
+61
+17
+146
+42
+127
+13
+21
+36
+46
+16
+93
+1
+90
+73
+53
+2
+70
+71
+83
+42
+70
+125
+124
+105
+46
+87
+69
+61
+42
+69
+139
+42
+149
+33
+139
+79
+1
+129
+148
+1
+62
+83
+74
+91
+2
+11
+21
+134
+118
+90
+65
+80
+148
+95
+91
+63
+68
+65
+91
+42
+140
+90
+64
+100
+1
+77
+67
+18
+1
+86
+8
+8
+96
+69
+37
+73
+4
+70
+48
+6
+98
+51
+48
+86
+90
+9
+58
+77
+17
+65
+38
+79
+65
+86
+62
+4
+89
+6
+1
+77
+42
+17
+86
+3
+95
+89
+8
+53
+64
+94
+44
+95
+27
+140
+86
+43
+38
+134
+67
+91
+65
+68
+57
+52
+151
+10
+17
+9
+48
+33
+29
+29
+61
+96
+97
+112
+6
+86
+62
+71
+27
+89
+43
+15
+91
+57
+64
+80
+77
+79
+96
+95
+42
+62
+127
+89
+91
+143
+42
+8
+85
+88
+68
+8
+70
+121
+43
+8
+73
+142
+65
+62
+37
+85
+97
+1
+8
+96
+42
+127
+64
+1
+61
+21
+139
+67
+65
+98
+77
+21
+2
+77
+73
+77
+79
+88
+91
+127
+129
+20
+28
+50
+135
+72
+44
+119
+21
+31
+1
+33
+17
+4
+152
+53
+146
+23
+91
+148
+43
+1
+77
+1
+139
+26
+80
+89
+38
+43
+129
+113
+1
+48
+74
+146
+68
+18
+77
+6
+87
+16
+149
+95
+8
+76
+77
+70
+8
+10
+12
+6
+148
+77
+127
+127
+89
+39
+63
+42
+62
+77
+21
+17
+140
+91
+33
+80
+95
+132
+65
+64
+48
+95
+124
+11
+16
+17
+96
+33
+91
+102
+99
+12
+48
+5
+11
+143
+62
+42
+73
+65
+4
+1
+66
+42
+89
+87
+17
+1
+33
+98
+96
+116
+101
+124
+142
+13
+113
+89
+2
+38
+65
+131
+17
+59
+13
+58
+68
+77
+68
+90
+25
+93
+99
+149
+48
+130
+36
+68
+95
+90
+70
+42
+120
+10
+140
+4
+140
+98
+4
+124
+89
+29
+18
+89
+6
+52
+1
+1
+42
+48
+8
+99
+63
+70
+17
+32
+74
+18
+33
+13
+2
+66
+86
+53
+95
+98
+37
+16
+135
+42
+100
+71
+8
+15
+149
+79
+53
+48
+129
+8
+77
+94
+19
+27
+8
+140
+145
+77
+132
+89
+61
+129
+42
+67
+17
+13
+68
+140
+50
+128
+33
+9
+139
+89
+89
+61
+121
+87
+95
+27
+140
+96
+21
+93
+95
+102
+8
+140
+64
+129
+30
+69
+43
+132
+129
+53
+124
+48
+2
+146
+39
+140
+141
+42
+90
+132
+89
+29
+118
+127
+74
+43
+86
+86
+21
+69
+65
+49
+8
+71
+136
+6
+129
+51
+2
+89
+90
+95
+89
+8
+68
+121
+44
+127
+62
+46
+16
+75
+142
+140
+1
+91
+20
+1
+8
+1
+3
+42
+141
+79
+15
+20
+48
+41
+87
+42
+43
+94
+115
+16
+48
+140
+42
+136
+119
+95
+95
+107
+1
+25
+144
+93
+73
+93
+60
+42
+144
+140
+96
+65
+73
+71
+27
+96
+141
+152
+30
+74
+94
+87
+14
+50
+77
+93
+89
+120
+1
+68
+98
+142
+21
+85
+42
+129
+139
+48
+1
+26
+86
+96
+43
+27
+65
+79
+65
+72
+9
+91
+67
+2
+10
+44
+68
+74
+139
+79
+69
+53
+127
+25
+130
+48
+10
+8
+74
+127
+45
+95
+39
+1
+17
+1
+79
+121
+140
+85
+38
+106
+91
+63
+90
+71
+131
+17
+90
+74
+5
+150
+94
+99
+86
+27
+4
+65
+57
+77
+21
+77
+3
+34
+73
+69
+74
+44
+90
+8
+87
+142
+61
+53
+118
+77
+96
+8
+80
+21
+31
+129
+38
+4
+41
+38
+73
+27
+149
+21
+70
+64
+7
+136
+6
+136
+64
+77
+104
+77
+9
+25
+61
+132
+27
+1
+89
+65
+148
+95
+121
+96
+8
+93
+65
+41
+129
+121
+34
+1
+8
+129
+31
+15
+46
+73
+134
+15
+10
+91
+16
+113
+87
+19
+89
+149
+29
+67
+42
+21
+7
+46
+15
+74
+53
+11
+149
+3
+11
+13
+62
+73
+60
+66
+75
+52
+128
+141
+74
+149
+93
+70
+65
+149
+17
+51
+67
+69
+84
+86
+141
+94
+48
+88
+45
+21
+71
+19
+89
+1
+83
+140
+28
+4
+149
+53
+71
+129
+87
+89
+42
+86
+21
+141
+77
+90
+21
+86
+129
+2
+89
+42
+131
+121
+149
+42
+53
+70
+98
+56
+88
+97
+53
+107
+136
+11
+68
+133
+90
+114
+89
+23
+146
+89
+104
+8
+57
+74
+75
+16
+96
+48
+143
+135
+1
+6
+1
+139
+41
+79
+65
+93
+63
+91
+19
+8
+71
+82
+70
+127
+3
+77
+88
+86
+62
+67
+42
+16
+5
+87
+21
+42
+133
+68
+21
+101
+64
+70
+20
+124
+10
+94
+95
+28
+33
+70
+65
+60
+129
+4
+115
+124
+8
+146
+62
+77
+64
+75
+135
+6
+4
+44
+42
+140
+93
+42
+3
+79
+21
+6
+96
+61
+93
+118
+62
+73
+83
+95
+68
+148
+65
+42
+88
+98
+129
+143
+80
+43
+28
+80
+42
+86
+108
+8
+89
+8
+88
+64
+87
+95
+6
+18
+145
+12
+8
+90
+119
+6
+111
+27
+30
+93
+17
+96
+70
+96
+86
+27
+139
+6
+27
+34
+43
+48
+2
+64
+4
+88
+65
+53
+77
+25
+74
+8
+8
+15
+151
+98
+77
+97
+33
+100
+43
+27
+21
+48
+65
+77
+124
+2
+25
+91
+149
+74
+8
+84
+67
+1
+65
+67
+48
+102
+91
+43
+52
+9
+42
+21
+8
+52
+74
+129
+114
+10
+42
+146
+44
+15
+98
+7
+52
+96
+78
+46
+30
+44
+8
+139
+16
+124
+94
+68
+8
+67
+38
+42
+7
+80
+113
+77
+23
+68
+77
+93
+87
+89
+142
+77
+149
+89
+14
+91
+15
+98
+64
+91
+77
+21
+98
+132
+90
+89
+91
+36
+42
+70
+10
+61
+88
+8
+15
+17
+67
+110
+12
+6
+11
+91
+72
+70
+48
+22
+64
+13
+139
+71
+139
+131
+62
+13
+79
+53
+4
+70
+128
+85
+79
+42
+97
+127
+8
+8
+1
+121
+88
+87
+119
+65
+95
+44
+85
+70
+52
+91
+91
+25
+84
+12
+105
+8
+30
+77
+76
+48
+79
+69
+137
+43
+66
+66
+20
+1
+14
+46
+3
+73
+66
+61
+48
+124
+64
+65
+50
+94
+31
+98
+96
+56
+144
+21
+21
+34
+2
+129
+17
+57
+127
+86
+89
+16
+48
+48
+113
+68
+42
+33
+52
+1
+26
+11
+136
+13
+8
+142
+95
+43
+14
+48
+59
+41
+6
+42
+90
+95
+69
+80
+139
+31
diff --git a/contextualized_topic_models/datasets/dataset.py b/contextualized_topic_models/datasets/dataset.py
index 66ca10c..e1f7262 100644
--- a/contextualized_topic_models/datasets/dataset.py
+++ b/contextualized_topic_models/datasets/dataset.py
@@ -2,23 +2,26 @@
 from torch.utils.data import Dataset
 import scipy.sparse
 
+
 class CTMDataset(Dataset):
 
     """Class to load BoW and the contextualized embeddings."""
 
-    def __init__(self, X_contextual, X_bow, idx2token):
-        """
-        Args
-            X : array-like, shape=(n_samples, n_features)
-                Document word matrix.
-        """
+    def __init__(self, X_contextual, X_bow, idx2token, labels=None):
+
         if X_bow.shape[0] != len(X_contextual):
             raise Exception("Wait! BoW and Contextual Embeddings have different sizes! "
                             "You might want to check if the BoW preparation method has removed some documents. ")
 
+        if labels is not None:
+            if labels.shape[0] != X_bow.shape[0]:
+                raise Exception(f"There is something wrong in the length of the labels (size: {labels.shape[0]}) "
+                                f"and the bow (len: {X_bow.shape[0]}). These two numbers should match.")
+
         self.X_bow = X_bow
         self.X_contextual = X_contextual
         self.idx2token = idx2token
+        self.labels = labels
 
     def __len__(self):
         """Return length of dataset."""
@@ -33,7 +36,15 @@ def __getitem__(self, i):
             X_bow = torch.FloatTensor(self.X_bow[i])
             X_contextual = torch.FloatTensor(self.X_contextual[i])
 
-        # TODO : update the parameter of the dictionary
-        return {'X_bow': X_bow, 'X_contextual': X_contextual}
+        return_dict = {'X_bow': X_bow, 'X_contextual': X_contextual}
+
+        if self.labels is not None:
+            labels = self.labels[i]
+            if type(labels) == scipy.sparse.csr.csr_matrix:
+                return_dict["labels"] = torch.FloatTensor(labels.todense())
+            else:
+                return_dict["labels"] = torch.FloatTensor(labels)
+
+        return return_dict
 
 
diff --git a/contextualized_topic_models/models/ctm.py b/contextualized_topic_models/models/ctm.py
index 6a61117..cc20a53 100644
--- a/contextualized_topic_models/models/ctm.py
+++ b/contextualized_topic_models/models/ctm.py
@@ -36,12 +36,22 @@ class CTM:
     :param num_epochs: int, number of epochs to train for, (default 100)
     :param reduce_on_plateau: bool, reduce learning rate by 10x on plateau of 10 epochs (default False)
     :param num_data_loader_workers: int, number of data loader workers (default cpu_count). set it to 0 if you are using Windows
+    :param label_size: int, number of total labels (default: 0)
+    :param loss_weights: dict, it contains the name of the weight parameter (key) and the weight (value) for each loss.
+    It supports only the weight parameter beta for now. If None, then the weights are set to 1 (default: None).
+
     """
 
     def __init__(self, bow_size, contextual_size, inference_type="combined", n_components=10, model_type='prodLDA',
-                 hidden_sizes=(100, 100), activation='softplus', dropout=0.2,
-                 learn_priors=True, batch_size=64, lr=2e-3, momentum=0.99,
-                 solver='adam', num_epochs=100, reduce_on_plateau=False, num_data_loader_workers=mp.cpu_count()):
+                 hidden_sizes=(100, 100), activation='softplus', dropout=0.2, learn_priors=True, batch_size=64,
+                 lr=2e-3, momentum=0.99, solver='adam', num_epochs=100, reduce_on_plateau=False,
+                 num_data_loader_workers=mp.cpu_count(), label_size=0, loss_weights=None):
+
+        self.device = (
+                torch.device("cuda")
+                if torch.cuda.is_available()
+                else torch.device("cpu")
+            )
 
         if self.__class__.__name__ == "CTM":
             raise Exception("You cannot call this class. Use ZeroShotTM or CombinedTM")
@@ -85,9 +95,15 @@ def __init__(self, bow_size, contextual_size, inference_type="combined", n_compo
         self.reduce_on_plateau = reduce_on_plateau
         self.num_data_loader_workers = num_data_loader_workers
 
+        if loss_weights:
+            self.weights = loss_weights
+        else:
+            self.weights = {"beta": 1}
+
         self.model = DecoderNetwork(
             bow_size, self.contextual_size, inference_type, n_components, model_type, hidden_sizes, activation,
-            dropout, learn_priors)
+            dropout, learn_priors, label_size=label_size)
+
         self.early_stopping = None
 
         # init optimizer
@@ -122,8 +138,7 @@ def __init__(self, bow_size, contextual_size, inference_type="combined", n_compo
         else:
             self.USE_CUDA = False
 
-        if self.USE_CUDA:
-            self.model = self.model.cuda()
+        self.model = self.model.to(self.device)
 
     def _loss(self, inputs, word_dists, prior_mean, prior_variance,
               posterior_mean, posterior_variance, posterior_log_variance):
@@ -145,9 +160,9 @@ def _loss(self, inputs, word_dists, prior_mean, prior_variance,
         # Reconstruction term
         RL = -torch.sum(inputs * torch.log(word_dists + 1e-10), dim=1)
 
-        loss = KL + RL
+        #loss = self.weights["beta"]*KL + RL
 
-        return loss.sum()
+        return KL, RL
 
     def _train_epoch(self, loader):
         """Train epoch."""
@@ -160,19 +175,37 @@ def _train_epoch(self, loader):
             X_bow = batch_samples['X_bow']
             X_bow = X_bow.reshape(X_bow.shape[0], -1)
             X_contextual = batch_samples['X_contextual']
+
+            if "labels" in batch_samples.keys():
+                labels = batch_samples["labels"]
+                labels = labels.reshape(labels.shape[0], -1)
+                labels = labels.to(self.device)
+            else:
+                labels = None
+
             if self.USE_CUDA:
                 X_bow = X_bow.cuda()
                 X_contextual = X_contextual.cuda()
 
             # forward pass
             self.model.zero_grad()
-            prior_mean, prior_variance, posterior_mean, posterior_variance, posterior_log_variance, word_dists =\
-                self.model(X_bow, X_contextual)
+            prior_mean, prior_variance, posterior_mean, posterior_variance,\
+            posterior_log_variance, word_dists, estimated_labels = self.model(X_bow, X_contextual, labels)
 
             # backward pass
-            loss = self._loss(
+            kl_loss, rl_loss = self._loss(
                 X_bow, word_dists, prior_mean, prior_variance,
                 posterior_mean, posterior_variance, posterior_log_variance)
+
+            loss = self.weights["beta"]*kl_loss + rl_loss
+            loss = loss.sum()
+
+            if labels is not None:
+                target_labels = torch.argmax(labels, 1)
+
+                label_loss = torch.nn.CrossEntropyLoss()(estimated_labels, target_labels)
+                loss += label_loss
+
             loss.backward()
             self.optimizer.step()
 
@@ -285,17 +318,34 @@ def _validation(self, loader):
             X_bow = X_bow.reshape(X_bow.shape[0], -1)
             X_contextual = batch_samples['X_contextual']
 
+            if "labels" in batch_samples.keys():
+                labels = batch_samples["labels"]
+                labels = labels.to(self.device)
+                labels = labels.reshape(labels.shape[0], -1)
+            else:
+                labels = None
+
             if self.USE_CUDA:
                 X_bow = X_bow.cuda()
                 X_contextual = X_contextual.cuda()
 
             # forward pass
             self.model.zero_grad()
-            prior_mean, prior_variance, posterior_mean, posterior_variance, posterior_log_variance, word_dists =\
-                self.model(X_bow, X_contextual)
-            loss = self._loss(X_bow, word_dists, prior_mean, prior_variance,
+            prior_mean, prior_variance, posterior_mean, posterior_variance, posterior_log_variance, word_dists, \
+            estimated_labels =\
+                self.model(X_bow, X_contextual, labels)
+
+            kl_loss, rl_loss = self._loss(X_bow, word_dists, prior_mean, prior_variance,
                               posterior_mean, posterior_variance, posterior_log_variance)
 
+            loss = self.weights["beta"]*kl_loss + rl_loss
+            loss = loss.sum()
+
+            if labels is not None:
+                target_labels = torch.argmax(labels, 1)
+                label_loss = torch.nn.CrossEntropyLoss()(estimated_labels, target_labels)
+                loss += label_loss
+
             # compute train loss
             samples_processed += X_bow.size()[0]
             val_loss += loss.item()
@@ -339,13 +389,20 @@ def get_doc_topic_distribution(self, dataset, n_samples=20):
                     X_bow = X_bow.reshape(X_bow.shape[0], -1)
                     X_contextual = batch_samples['X_contextual']
 
+                    if "labels" in batch_samples.keys():
+                        labels = batch_samples["labels"]
+                        labels = labels.to(self.device)
+                        labels = labels.reshape(labels.shape[0], -1)
+                    else:
+                        labels = None
+
                     if self.USE_CUDA:
                         X_bow = X_bow.cuda()
                         X_contextual = X_contextual.cuda()
 
                     # forward pass
                     self.model.zero_grad()
-                    collect_theta.extend(self.model.get_theta(X_bow, X_contextual).cpu().numpy().tolist())
+                    collect_theta.extend(self.model.get_theta(X_bow, X_contextual, labels).cpu().numpy().tolist())
 
                 pbar.update(1)
                 pbar.set_description("Sampling: [{}/{}]".format(sample_index + 1, n_samples))
@@ -538,60 +595,18 @@ def get_ldavis_data_format(self, vocab, dataset, n_samples):
 class ZeroShotTM(CTM):
     """ZeroShotTM, as described in https://arxiv.org/pdf/2004.07737v1.pdf
 
-    :param bow_size: int, dimension of input
-    :param contextual_size: int, dimension of input that comes from BERT embeddings
-    :param n_components: int, number of topic components, (default 10)
-    :param model_type: string, 'prodLDA' or 'LDA' (default 'prodLDA')
-    :param hidden_sizes: tuple, length = n_layers, (default (100, 100))
-    :param activation: string, 'softplus', 'relu', (default 'softplus')
-    :param dropout: float, dropout to use (default 0.2)
-    :param learn_priors: bool, make priors a learnable parameter (default True)
-    :param batch_size: int, size of batch to use for training (default 64)
-    :param lr: float, learning rate to use for training (default 2e-3)
-    :param momentum: float, momentum to use for training (default 0.99)
-    :param solver: string, optimizer 'adam' or 'sgd' (default 'adam')
-    :param num_epochs: int, number of epochs to train for, (default 100)
-    :param reduce_on_plateau: bool, reduce learning rate by 10x on plateau of 10 epochs (default False)
-    :param num_data_loader_workers: int, number of data loader workers (default cpu_count). set it to 0 if you are using Windows
     """
 
-    def __init__(self, bow_size, contextual_size, n_components=10, model_type='prodLDA',
-                 hidden_sizes=(100, 100), activation='softplus', dropout=0.2,
-                 learn_priors=True, batch_size=64, lr=2e-3, momentum=0.99,
-                 solver='adam', num_epochs=100, reduce_on_plateau=False, num_data_loader_workers=mp.cpu_count()):
+    def __init__(self, **kwargs):
         inference_type = "zeroshot"
-        super().__init__(bow_size, contextual_size, inference_type, n_components, model_type,
-                         hidden_sizes, activation, dropout,
-                         learn_priors, batch_size, lr, momentum,
-                         solver, num_epochs, reduce_on_plateau, num_data_loader_workers)
+        super().__init__(**kwargs, inference_type=inference_type)
 
 
 class CombinedTM(CTM):
     """CombinedTM, as described in https://arxiv.org/pdf/2004.03974.pdf
 
-    :param bow_size: int, dimension of input
-    :param contextual_size: int, dimension of input that comes from BERT embeddings
-    :param n_components: int, number of topic components, (default 10)
-    :param model_type: string, 'prodLDA' or 'LDA' (default 'prodLDA')
-    :param hidden_sizes: tuple, length = n_layers, (default (100, 100))
-    :param activation: string, 'softplus', 'relu', (default 'softplus')
-    :param dropout: float, dropout to use (default 0.2)
-    :param learn_priors: bool, make priors a learnable parameter (default True)
-    :param batch_size: int, size of batch to use for training (default 64)
-    :param lr: float, learning rate to use for training (default 2e-3)
-    :param momentum: float, momentum to use for training (default 0.99)
-    :param solver: string, optimizer 'adam' or 'sgd' (default 'adam')
-    :param num_epochs: int, number of epochs to train for, (default 100)
-    :param reduce_on_plateau: bool, reduce learning rate by 10x on plateau of 10 epochs (default False)
-    :param num_data_loader_workers: int, number of data loader workers (default cpu_count). set it to 0 if you are using Windows
     """
 
-    def __init__(self, bow_size, contextual_size, n_components=10, model_type='prodLDA',
-                 hidden_sizes=(100, 100), activation='softplus', dropout=0.2,
-                 learn_priors=True, batch_size=64, lr=2e-3, momentum=0.99,
-                 solver='adam', num_epochs=100, reduce_on_plateau=False, num_data_loader_workers=mp.cpu_count()):
+    def __init__(self, **kwargs):
         inference_type = "combined"
-        super().__init__(bow_size, contextual_size, inference_type, n_components, model_type,
-                         hidden_sizes, activation, dropout,
-                         learn_priors, batch_size, lr, momentum,
-                         solver, num_epochs, reduce_on_plateau, num_data_loader_workers)
+        super().__init__(**kwargs, inference_type=inference_type)
diff --git a/contextualized_topic_models/networks/decoding_network.py b/contextualized_topic_models/networks/decoding_network.py
index 5185b59..7beb60d 100644
--- a/contextualized_topic_models/networks/decoding_network.py
+++ b/contextualized_topic_models/networks/decoding_network.py
@@ -10,7 +10,7 @@ class DecoderNetwork(nn.Module):
 
     def __init__(self, input_size, bert_size, infnet, n_components=10, model_type='prodLDA',
                  hidden_sizes=(100,100), activation='softplus', dropout=0.2,
-                 learn_priors=True):
+                 learn_priors=True, label_size=0):
         """
         Initialize InferenceNetwork.
 
@@ -43,15 +43,19 @@ def __init__(self, input_size, bert_size, infnet, n_components=10, model_type='p
         self.learn_priors = learn_priors
         self.topic_word_matrix = None
 
+
         if infnet == "zeroshot":
             self.inf_net = ContextualInferenceNetwork(
-                input_size, bert_size, n_components, hidden_sizes, activation)
+                input_size, bert_size, n_components, hidden_sizes, activation, label_size=label_size)
         elif infnet == "combined":
             self.inf_net = CombinedInferenceNetwork(
-                input_size, bert_size, n_components, hidden_sizes, activation)
+                input_size, bert_size, n_components, hidden_sizes, activation, label_size=label_size)
         else:
             raise Exception('Missing infnet parameter, options are zeroshot and combined')
 
+        if label_size != 0:
+            self.label_classification = nn.Linear(n_components, label_size)
+
         # init prior parameters
         # \mu_1k = log \alpha_k + 1/K \sum_i log \alpha_i;
         # \alpha = 1 \forall \alpha
@@ -91,10 +95,10 @@ def reparameterize(mu, logvar):
         eps = torch.randn_like(std)
         return eps.mul(std).add_(mu)
 
-    def forward(self, x, x_bert):
+    def forward(self, x, x_bert, labels=None):
         """Forward pass."""
         # batch_size x n_components
-        posterior_mu, posterior_log_sigma = self.inf_net(x, x_bert)
+        posterior_mu, posterior_log_sigma = self.inf_net(x, x_bert, labels)
         posterior_sigma = torch.exp(posterior_log_sigma)
 
         # generate samples from theta
@@ -115,15 +119,24 @@ def forward(self, x, x_bert):
             self.topic_word_matrix = beta
             word_dist = torch.matmul(theta, beta)
             # word_dist: batch_size x input_size
+        else:
+            raise NotImplementedError("Model Type Not Implemented")
+
+        # classify labels
+
+        estimated_labels = None
+
+        if labels is not None:
+            estimated_labels = self.label_classification(theta)
 
         return self.prior_mean, self.prior_variance, \
-            posterior_mu, posterior_sigma, posterior_log_sigma, word_dist
+            posterior_mu, posterior_sigma, posterior_log_sigma, word_dist, estimated_labels
 
-    def get_theta(self, x, x_bert):
+    def get_theta(self, x, x_bert, labels=None):
         with torch.no_grad():
             # batch_size x n_components
-            posterior_mu, posterior_log_sigma = self.inf_net(x, x_bert)
-            posterior_sigma = torch.exp(posterior_log_sigma)
+            posterior_mu, posterior_log_sigma = self.inf_net(x, x_bert, labels)
+            #posterior_sigma = torch.exp(posterior_log_sigma)
 
             # generate samples from theta
             theta = F.softmax(
diff --git a/contextualized_topic_models/networks/inference_network.py b/contextualized_topic_models/networks/inference_network.py
index 2b8774a..f028738 100644
--- a/contextualized_topic_models/networks/inference_network.py
+++ b/contextualized_topic_models/networks/inference_network.py
@@ -8,8 +8,9 @@ class ContextualInferenceNetwork(nn.Module):
     """Inference Network."""
 
     def __init__(self, input_size, bert_size, output_size, hidden_sizes,
-                 activation='softplus', dropout=0.2):
+                 activation='softplus', dropout=0.2, label_size=0):
         """
+        # TODO: check dropout in main caller
         Initialize InferenceNetwork.
 
         Args
@@ -38,8 +39,8 @@ def __init__(self, input_size, bert_size, output_size, hidden_sizes,
         elif activation == 'relu':
             self.activation = nn.ReLU()
 
-        self.input_layer = nn.Linear(input_size+input_size, hidden_sizes[0])
-        self.adapt_bert = nn.Linear(bert_size, hidden_sizes[0])
+        self.input_layer = nn.Linear(bert_size + label_size, hidden_sizes[0])
+        #self.adapt_bert = nn.Linear(bert_size, hidden_sizes[0])
 
         self.hiddens = nn.Sequential(OrderedDict([
             ('l_{}'.format(i), nn.Sequential(nn.Linear(h_in, h_out), self.activation))
@@ -53,11 +54,16 @@ def __init__(self, input_size, bert_size, output_size, hidden_sizes,
 
         self.dropout_enc = nn.Dropout(p=self.dropout)
 
-    def forward(self, x, x_bert):
+    def forward(self, x, x_bert, labels=None):
         """Forward pass."""
-        x_bert = self.adapt_bert(x_bert)
 
-        x = self.activation(x_bert)
+        x = x_bert
+        if labels:
+            x = torch.cat((x_bert, labels), 1)
+
+        x = self.input_layer(x)
+
+        x = self.activation(x)
         x = self.hiddens(x)
         x = self.dropout_enc(x)
         mu = self.f_mu_batchnorm(self.f_mu(x))
@@ -66,14 +72,12 @@ def forward(self, x, x_bert):
         return mu, log_sigma
 
 
-
-
 class CombinedInferenceNetwork(nn.Module):
 
     """Inference Network."""
 
     def __init__(self, input_size, bert_size, output_size, hidden_sizes,
-                 activation='softplus', dropout=0.2):
+                 activation='softplus', dropout=0.2, label_size=0):
         """
         Initialize InferenceNetwork.
 
@@ -103,9 +107,10 @@ def __init__(self, input_size, bert_size, output_size, hidden_sizes,
         elif activation == 'relu':
             self.activation = nn.ReLU()
 
-        self.input_layer = nn.Linear(input_size+input_size, hidden_sizes[0])
+
         self.adapt_bert = nn.Linear(bert_size, input_size)
-        self.bert_layer = nn.Linear(hidden_sizes[0], hidden_sizes[0])
+        #self.bert_layer = nn.Linear(hidden_sizes[0], hidden_sizes[0])
+        self.input_layer = nn.Linear(input_size + input_size + label_size, hidden_sizes[0])
 
         self.hiddens = nn.Sequential(OrderedDict([
             ('l_{}'.format(i), nn.Sequential(nn.Linear(h_in, h_out), self.activation))
@@ -119,10 +124,15 @@ def __init__(self, input_size, bert_size, output_size, hidden_sizes,
 
         self.dropout_enc = nn.Dropout(p=self.dropout)
 
-    def forward(self, x, x_bert):
+    def forward(self, x, x_bert, labels=None):
         """Forward pass."""
         x_bert = self.adapt_bert(x_bert)
+
         x = torch.cat((x, x_bert), 1)
+
+        if labels is not None:
+            x = torch.cat((x, labels), 1)
+
         x = self.input_layer(x)
 
         x = self.activation(x)
diff --git a/contextualized_topic_models/utils/data_preparation.py b/contextualized_topic_models/utils/data_preparation.py
index 844021f..61edb45 100644
--- a/contextualized_topic_models/utils/data_preparation.py
+++ b/contextualized_topic_models/utils/data_preparation.py
@@ -4,7 +4,7 @@
 import warnings
 from contextualized_topic_models.datasets.dataset import CTMDataset
 from sklearn.feature_extraction.text import CountVectorizer
-
+from sklearn.preprocessing import OneHotEncoder
 
 def get_bag_of_words(data, min_length):
     """
@@ -43,13 +43,19 @@ def __init__(self, contextualized_model=None):
         self.vocab = []
         self.id2token = {}
         self.vectorizer = None
+        self.label_encoder = None
 
-    def load(self, contextualized_embeddings, bow_embeddings, id2token):
-        return CTMDataset(contextualized_embeddings, bow_embeddings, id2token)
+    def load(self, contextualized_embeddings, bow_embeddings, id2token, labels=None):
+        return CTMDataset(contextualized_embeddings, bow_embeddings, id2token, labels)
 
-    def fit(self, text_for_contextual, text_for_bow):
+    def fit(self, text_for_contextual, text_for_bow, labels=None):
         """
         This method fits the vectorizer and gets the embeddings from the contextual model
+
+        :param text_for_contextual: list of unpreprocessed documents to generate the contextualized embeddings
+        :param text_for_bow: list of preprocessed documents for creating the bag-of-words
+        :param labels: list of labels associated with each document (optional).
+
         """
 
         if self.contextualized_model is None:
@@ -63,9 +69,15 @@ def fit(self, text_for_contextual, text_for_bow):
         self.vocab = self.vectorizer.get_feature_names()
         self.id2token = {k: v for k, v in zip(range(0, len(self.vocab)), self.vocab)}
 
-        return CTMDataset(train_contextualized_embeddings, train_bow_embeddings, self.id2token)
+        if labels:
+            self.label_encoder = OneHotEncoder()
+            encoded_labels = self.label_encoder.fit_transform(np.array([labels]).reshape(-1, 1))
+        else:
+            encoded_labels = None
 
-    def transform(self, text_for_contextual, text_for_bow=None):
+        return CTMDataset(train_contextualized_embeddings, train_bow_embeddings, self.id2token, encoded_labels)
+
+    def transform(self, text_for_contextual, text_for_bow=None, labels=None):
         """
         This methods create the input for the prediction. Essentially, it creates the embeddings with the contextualized
         model of choice and with trained vectorizer.
@@ -87,4 +99,9 @@ def transform(self, text_for_contextual, text_for_bow=None):
             test_bow_embeddings = scipy.sparse.csr_matrix(np.zeros((len(text_for_contextual), 1)))
         test_contextualized_embeddings = bert_embeddings_from_list(text_for_contextual, self.contextualized_model)
 
-        return CTMDataset(test_contextualized_embeddings, test_bow_embeddings, self.id2token)
+        if labels:
+            encoded_labels = self.label_encoder.transform(np.array([labels]).reshape(-1, 1))
+        else:
+            encoded_labels = None
+
+        return CTMDataset(test_contextualized_embeddings, test_bow_embeddings, self.id2token, encoded_labels)


Test patch:
diff --git a/tests/test_contextualized_topic_models.py b/tests/test_contextualized_topic_models.py
index dcffff7..6780055 100644
--- a/tests/test_contextualized_topic_models.py
+++ b/tests/test_contextualized_topic_models.py
@@ -24,6 +24,23 @@ def data_dir(root_dir):
     return root_dir + "/../contextualized_topic_models/data/"
 
 
+def test_labels_set(data_dir):
+
+    with open(data_dir + '/gnews/GoogleNews.txt') as filino:
+        data = filino.readlines()
+
+    with open(data_dir + '/gnews/GoogleNews_LABEL.txt') as filino:
+        labels = list(map(lambda x:x.replace("\n", ""), filino.readlines()))
+
+    tp = TopicModelDataPreparation("distiluse-base-multilingual-cased")
+
+    training_dataset = tp.fit(data[:100], data[:100], labels[:100])
+
+    ctm = CombinedTM(reduce_on_plateau=True, solver='sgd', bow_size=len(tp.vocab),
+                     contextual_size=512, num_epochs=2, n_components=5, batch_size=2, label_size=len(set(labels[:100])))
+    ctm.fit(training_dataset)
+
+
 def test_validation_set(data_dir):
 
     with open(data_dir + '/gnews/GoogleNews.txt') as filino:
@@ -66,6 +83,13 @@ def test_training_all_classes_ctm(data_dir):
     topics = ctm.get_topic_lists(2)
     assert len(topics) == 5
 
+    ctm = CombinedTM(bow_size=len(tp.vocab), contextual_size=512, num_epochs=1, n_components=5,loss_weights={"beta": 10})
+    ctm.fit(training_dataset)  # run the model
+    assert ctm.weights == {"beta": 10}
+
+    topics = ctm.get_topic_lists(2)
+    assert len(topics) == 5
+
     testing_dataset = tp.transform(data, data)
     predictions = ctm.get_doc_topic_distribution(testing_dataset, n_samples=2)