diff --git a/ComputingTasks.cc b/ComputingTasks.cc
index 4cc96f966207086fcfa9e22d4b7e8424ff5043ca..08740ebcabd2daf4cdb62ddd3544ab3d4e09f341 100644
--- a/ComputingTasks.cc
+++ b/ComputingTasks.cc
@@ -27,6 +27,11 @@ using namespace std;
 #include "ComputingTasks.hh"
 #include "Statement.hh"
 
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/tokenizer.hpp>
+
 SteadyStatement::SteadyStatement(const OptionsList &options_list_arg) :
   options_list(options_list_arg)
 {
@@ -1345,6 +1350,144 @@ SvarIdentificationStatement::writeOutput(ostream &output, const string &basename
 MarkovSwitchingStatement::MarkovSwitchingStatement(const OptionsList &options_list_arg) :
   options_list(options_list_arg)
 {
+  OptionsList::num_options_t::const_iterator it_num = options_list.num_options.find("ms.restrictions");
+  if (it_num != options_list.num_options.end())
+    {
+      using namespace boost;
+      OptionsList::num_options_t::const_iterator it_num_regimes =
+        options_list.num_options.find("ms.number_of_regimes");
+      if (it_num_regimes ==  options_list.num_options.end())
+        {
+          cerr << "ERROR: should not arrive here: MarkovSwitchingStatement::checkPass" << endl;
+          exit(EXIT_FAILURE);
+        }
+      int num_regimes = lexical_cast< int >(it_num_regimes->second);
+
+      vector<string> tokenizedRestrictions;
+      split(tokenizedRestrictions, it_num->second, is_any_of("["), token_compress_on);
+      for (vector<string>::iterator it = tokenizedRestrictions.begin();
+            it != tokenizedRestrictions.end(); it++ )
+        if (it->size() > 0)
+          {
+            vector<string> restriction;
+            split(restriction, *it, is_any_of("], "));
+            for (vector<string>::iterator it1 = restriction.begin();
+                 it1 != restriction.end(); )
+              if (it1->empty())
+                restriction.erase(it1);
+              else
+                it1++;
+
+            if (restriction.size() != 3)
+              {
+                cerr << "ERROR: restrictions in the subsample statement must be specified in the form "
+                     << "[current_period_regime, next_period_regime, transition_probability]" << endl;
+                exit(EXIT_FAILURE);
+              }
+
+            try
+              {
+                int from_regime = lexical_cast< int >(restriction[0]);
+                int to_regime = lexical_cast< int >(restriction[1]);
+                if (from_regime > num_regimes || to_regime > num_regimes)
+                  {
+                    cerr << "ERROR: the regimes specified in the restrictions option must be "
+                         << "<= the number of regimes specified in the number_of_regimes option" << endl;
+                    exit(EXIT_FAILURE);
+                  }
+
+                if (restriction_map.find(make_pair(from_regime, to_regime)) !=
+                    restriction_map.end())
+                  {
+                    cerr << "ERROR: two restrictions were given for: " << from_regime << ", "
+                         << to_regime << endl;
+                    exit(EXIT_FAILURE);
+                  }
+
+                double transition_probability = lexical_cast< double >(restriction[2]);
+                if (transition_probability > 1.0)
+                  {
+                    cerr << "ERROR: the transition probability, " << transition_probability
+                         << " must be less than 1" << endl;
+                    exit(EXIT_FAILURE);
+                  }
+                restriction_map[make_pair(from_regime, to_regime)] = transition_probability;
+              }
+            catch (const bad_lexical_cast &)
+              {
+                cerr << "ERROR: The first two arguments for a restriction must be integers "
+                     << "specifying the regime and the last must be a double specifying the "
+                     << "transition probability. You wrote [" << *it << endl;
+                exit(EXIT_FAILURE);
+              }
+          }
+    }
+}
+
+void
+MarkovSwitchingStatement::checkPass(ModFileStructure &mod_file_struct)
+{
+  OptionsList::num_options_t::const_iterator it_num = options_list.num_options.find("ms.restrictions");
+  if (it_num != options_list.num_options.end())
+    {
+      using namespace boost;
+      OptionsList::num_options_t::const_iterator it_num_regimes =
+        options_list.num_options.find("ms.number_of_regimes");
+      int num_regimes = lexical_cast< int >(it_num_regimes->second);
+      vector<double> col_trans_prob_sum (num_regimes, 0);
+      vector<double> row_trans_prob_sum (num_regimes, 0);
+      vector<bool> all_restrictions_in_row (num_regimes, true);
+      vector<bool> all_restrictions_in_col (num_regimes, true);
+      for (int row=0; row<num_regimes; row++)
+        for (int col=0; col<num_regimes; col++)
+          if (restriction_map.find(make_pair(row+1, col+1)) != restriction_map.end())
+            {
+              row_trans_prob_sum[row] += restriction_map[make_pair(row+1, col+1)];
+              col_trans_prob_sum[col] += restriction_map[make_pair(row+1, col+1)];
+            }
+          else
+            {
+              all_restrictions_in_row[row] = false;
+              all_restrictions_in_col[col] = false;
+            }
+
+      for (int i=0; i<num_regimes; i++)
+        {
+          if (all_restrictions_in_row[i])
+          {
+            if (row_trans_prob_sum[i] != 1.0)
+              {
+                cerr << "ERROR: When all transitions probabilities are specified for a certain "
+                     << "regime, they must sum to 1" << endl;
+                exit(EXIT_FAILURE);
+              }
+          }
+        else
+          if (row_trans_prob_sum[i] >= 1.0)
+            {
+              cerr << "ERROR: When transition probabilites are not specified for every regime, "
+                   << "their sum must be < 1" << endl;
+              exit(EXIT_FAILURE);
+            }
+
+        if (all_restrictions_in_col[i])
+          {
+            if (col_trans_prob_sum[i] != 1.0)
+              {
+                cerr << "ERROR: When all transitions probabilities are specified for a certain "
+                     << "regime, they must sum to 1" << endl;
+                exit(EXIT_FAILURE);
+              }
+          }
+        else
+          if (col_trans_prob_sum[i] >= 1.0)
+            {
+              cerr << "ERROR: When transition probabilites are not specified for every regime, "
+                   << "their sum must be < 1" << endl;
+              exit(EXIT_FAILURE);
+            }
+        }
+    }
 }
 
 void
@@ -1353,18 +1496,21 @@ MarkovSwitchingStatement::writeOutput(ostream &output, const string &basename) c
   bool isDurationAVec = true;
   string infStr("Inf");
   OptionsList::num_options_t::const_iterator itChain, itNOR, itDuration;
+  map<pair<int, int>, double >::const_iterator itR;
 
   itChain = options_list.num_options.find("ms.chain");
   if (itChain == options_list.num_options.end())
     {
-      cerr << "MarkovSwitchingStatement::writeOutput() Should not arrive here (1). Please report this to the Dynare Team." << endl;
+      cerr << "MarkovSwitchingStatement::writeOutput() Should not arrive here (1). "
+           << "Please report this to the Dynare Team." << endl;
       exit(EXIT_FAILURE);
     }
 
   itDuration = options_list.num_options.find("ms.duration");
   if (itDuration == options_list.num_options.end())
     {
-      cerr << "MarkovSwitchingStatement::writeOutput() Should not arrive here (2). Please report this to the Dynare Team." << endl;
+      cerr << "MarkovSwitchingStatement::writeOutput() Should not arrive here (2). "
+           << "Please report this to the Dynare Team." << endl;
       exit(EXIT_FAILURE);
     }
   else if (atof(itDuration->second.c_str()) || infStr.compare(itDuration->second) == 0)
@@ -1383,9 +1529,16 @@ MarkovSwitchingStatement::writeOutput(ostream &output, const string &basename) c
       }
   else
     {
-      cerr << "MarkovSwitchingStatement::writeOutput() Should not arrive here (3). Please report this to the Dynare Team." << endl;
+      cerr << "MarkovSwitchingStatement::writeOutput() Should not arrive here (3). "
+           << "Please report this to the Dynare Team." << endl;
       exit(EXIT_FAILURE);
     }
+
+  int restrictions_index = 0;
+  for (itR=restriction_map.begin(); itR != restriction_map.end(); itR++)
+    output << "options_.ms.ms_chain(" << itChain->second << ").restrictions("
+           << ++restrictions_index << ") = {[" << itR->first.first << ", "
+           << itR->first.second << ", " << itR->second << "]};" << endl;
 }
 
 SvarStatement::SvarStatement(const OptionsList &options_list_arg) :
diff --git a/ComputingTasks.hh b/ComputingTasks.hh
index 397139aeb7483a173f9d3618e7cca6aca54c1336..bba0176e07903ebeaaa6f7a49b0e6f37dcfdbcc8 100644
--- a/ComputingTasks.hh
+++ b/ComputingTasks.hh
@@ -542,8 +542,10 @@ class MarkovSwitchingStatement : public Statement
 {
 private:
   const OptionsList options_list;
+  map <pair<int, int >, double > restriction_map;
 public:
   MarkovSwitchingStatement(const OptionsList &options_list_arg);
+  virtual void checkPass(ModFileStructure &mod_file_struct);
   virtual void writeOutput(ostream &output, const string &basename) const;
 };
 
diff --git a/DynareBison.yy b/DynareBison.yy
index edbc812c8b2648e621128f4db5bd94ca6f2dd8bf..7df717480940bae01c6b73720cece444a760f527 100644
--- a/DynareBison.yy
+++ b/DynareBison.yy
@@ -151,7 +151,7 @@ class ParsingDriver;
 %token GSIG2_LMDM Q_DIAG FLAT_PRIOR NCSK NSTD
 %token INDXPARR INDXOVR INDXAP APBAND INDXIMF IMFBAND INDXFORE FOREBAND INDXGFOREHAT INDXGIMFHAT
 %token INDXESTIMA INDXGDLS EQ_MS FILTER_COVARIANCE FILTER_DECOMPOSITION
-%token EQ_CMS TLINDX TLNUMBER BANACT
+%token EQ_CMS TLINDX TLNUMBER BANACT RESTRICTIONS
 %token OUTPUT_FILE_TAG DRAWS_NBR_BURN_IN_1 DRAWS_NBR_BURN_IN_2 HORIZON
 %token SBVAR TREND_VAR DEFLATOR GROWTH_FACTOR MS_IRF MS_VARIANCE_DECOMPOSITION
 %token MS_ESTIMATION MS_SIMULATION MS_COMPUTE_MDD MS_COMPUTE_PROBABILITIES MS_FORECAST
@@ -175,7 +175,7 @@ class ParsingDriver;
 %type <node_val> expression expression_or_empty
 %type <node_val> equation hand_side
 %type <string_val> non_negative_number signed_number signed_integer date_number
-%type <string_val> filename symbol prior_distribution
+%type <string_val> filename symbol prior_distribution vec_of_vec_value vec_value_list
 %type <string_val> vec_value_1 vec_value signed_inf signed_number_w_inf
 %type <string_val> range prior_pdf_string vec_value_w_inf vec_value_1_w_inf
 %type <symbol_type_val> change_type_arg
@@ -741,6 +741,7 @@ ms_options_list : ms_options_list COMMA ms_options
 
 ms_options : o_chain
            | o_duration
+           | o_restrictions
            | o_number_of_regimes
            ;
 
@@ -2219,6 +2220,9 @@ o_cnum : CNUM EQUAL INT_NUMBER {driver.option_num("ms.cnum",$3); };
 o_k_order_solver : K_ORDER_SOLVER {driver.option_num("k_order_solver","1"); };
 o_pruning : PRUNING { driver.option_num("pruning", "1"); };
 o_chain : CHAIN EQUAL INT_NUMBER { driver.option_num("ms.chain",$3); };
+o_restrictions : RESTRICTIONS EQUAL vec_of_vec_value
+                 { driver.option_num("ms.restrictions",$3); }
+               ;
 o_duration : DURATION EQUAL non_negative_number
              { driver.option_num("ms.duration",$3); }
            | DURATION EQUAL vec_value_w_inf
@@ -2384,6 +2388,20 @@ vec_value : vec_value_1 ']' { $1->append("]"); $$ = $1; }
           | vec_value_1 COMMA ']' { $1->append("]"); $$ = $1; }
           ;
 
+vec_value_list : vec_value_list COMMA vec_value
+                 {
+                   $1->append(",");
+                   $1->append(*$3);
+                   delete $3;
+                   $$ = $1;
+                 }
+               | vec_value
+                 { $$ = $1; }
+               ;
+
+vec_of_vec_value : '[' vec_value_list ']' { $$ = $2; }
+                 | vec_value  { $$ = $1; };
+
 vec_value_1_w_inf : '[' signed_number_w_inf
                     { $2->insert(0, "["); $$ = $2;}
                   | vec_value_1_w_inf signed_number_w_inf
diff --git a/DynareFlex.ll b/DynareFlex.ll
index 824476d993e8709c151ba8c3e299d87a3f6c1c34..2d91d096e1330661937395ceac979b689a4cf6e0 100644
--- a/DynareFlex.ll
+++ b/DynareFlex.ll
@@ -282,6 +282,7 @@ string eofbuff;
 <DYNARE_STATEMENT>vlistper {return token::VLISTPER;}
 <DYNARE_STATEMENT>restriction_fname {return token::RESTRICTION_FNAME;}
 <DYNARE_STATEMENT>nlags {return token::NLAGS;}
+<DYNARE_STATEMENT>restrictions {return token::RESTRICTIONS;}
 <DYNARE_STATEMENT>cross_restrictions {return token::CROSS_RESTRICTIONS;}
 <DYNARE_STATEMENT>contemp_reduced_form {return token::CONTEMP_REDUCED_FORM;}
 <DYNARE_STATEMENT>real_pseudo_forecast {return token::REAL_PSEUDO_FORECAST;}