'''
.. module:: _dsgeparser
   :platform: Linux
   :synopsis: This is the (private) module responsible for carefully extracting meaningful information from the DSGE model templated
              files. In here we make much use of Regex patterns as we are extracting information from the mod file lines.

.. moduleauthor:: Eric M. Scheffel <eric.scheffel@nottingham.edu.cn>


'''
import re
from copy import deepcopy
import numpy.matlib as mat
import numpy as np
import sys
import os
# This used to import sympycore, but should now also work with sympy
import sympycore as SP


#TODO: why have these as nested functions?
def populate_model_stage_one(self, secs):
    """
    1st stage population of DSGE model.  Does not need Steady State.
    """
    
    # Establish the timing convention of variables in the model file
    self = def_timing(self,**self._vtiming)    
    
    # This is a special dictionary which can be handed over to the template engines (i.e. Jinja2)
    if 'template_paramdic' not in dir(self): self.template_paramdic = {}


    # Get all information from the varvec section
    if all([False if 'None' in x else True for x in secs['varvec'][0]]):
        # match something like [1]  z(t):eps_z(t):techshock{exo}[log,hp]
        vtexp =  re.compile('^.*?\[.*?\]\s*(?P<vari>.+?)\s*:\s*(?P<varn>.+?)\s*\{(?P<vtype>[^\[]+)}\s*(?P<mod>\[.*?\]){0,1}')
        # match something like [15] x2(t):wrec2{con}[log,hp] OR [1] z(t):eps_z(t):techshock{exo}[log,hp]
        viiexp = re.compile('^.*?\[.*?\]\s*(?P<vari>.+?)\s*:\s*(?P<viid>.+?)\s*:\s*(?P<varn>.+?)\s*\{(?P<vtype>[^\[]+)}\s*(?P<mod>\[.*?\]){0,1}')
        voexp =  re.compile('^.*?\[.*?\]\s*(?P<vari>@.+?):(?P<varn>[^\[]+)\s*(?P<mod>\[.*?\]){0,1}')
        vardic = {}
        audic = {}
        vardic['endo'] = {}
        audic['endo'] = {}
        vardic['exo'] = {}
        audic['exo'] = {}
        vardic['con'] = {}
        audic['con'] = {}
        vardic['other'] = {}
        vardic['endo']['var'] = []
        vardic['endo']['mod'] = []
        vardic['exo']['var'] = []
        vardic['exo']['mod'] = []
        vardic['con']['var'] = []
        vardic['con']['mod'] = []
        vardic['other']['var'] = []
        vardic['other']['mod'] = []
        audic['endo']['var'] = []
        audic['endo']['mod'] = []
        audic['con']['var'] = []
        audic['con']['mod'] = []
        audic['exo']['var'] = []
        audic['exo']['mod'] = []

        for x in secs['varvec'][0]:
            if viiexp.search(x):
                ma = viiexp.search(x)
                vari = ma.group('vari').strip()
                viid = ma.group('viid').strip()
                varn = ma.group('varn').strip()
                vtype = ma.group('vtype').strip()
                mods = ma.group('mod')
                vardic[vtype]['var'].append([vari,varn,viid])
                if mods != None:
                    mods = mods.strip()
                    if ',' in mods:
                        vardic[vtype]['mod'].append(mods[1:-1].strip().split(','))
                    else:
                        vardic[vtype]['mod'].append([mods[1:-1].strip(),])
                else:
                    vardic[vtype]['mod'].append([])

            elif vtexp.search(x):
                ma = vtexp.search(x)
                vari = ma.group('vari').strip()
                varn = ma.group('varn').strip()
                vtype = ma.group('vtype').strip()
                mods = ma.group('mod')
                vardic[vtype]['var'].append([vari,varn])
                if mods != None:
                    mods = mods.strip()
                    if ',' in mods:
                        vardic[vtype]['mod'].append(mods[1:-1].strip().split(','))
                    else:
                        vardic[vtype]['mod'].append([mods[1:-1].strip(),])
                else:
                    vardic[vtype]['mod'].append([])

            elif voexp.search(x):
                ma = voexp.search(x)
                # Slice off the @
                vari = ma.group('vari')[1:].strip()
                varn = ma.group('varn').strip()
                mods = ma.group('mod')
                vardic['other']['var'].append([vari,varn])
                if mods != None:
                    mods = mods.strip()
                    if ',' in mods:
                        vardic['other']['mod'].append(mods[1:-1].strip().split(','))
                    else:
                        vardic['other']['mod'].append([mods[1:-1].strip(),])
                else:
                    vardic['other']['mod'].append([])

        self.nendo = len(vardic['endo']['var'])
        self.nexo = len(vardic['exo']['var'])
        self.ncon = len(vardic['con']['var'])
        self.nother = len(vardic['other']['var'])
        self.nstat = self.nendo+self.nexo
        self.nall = self.nstat+self.ncon
        self.vardic = vardic
        self.audic = audic
        # Save for template instantiation
        self.template_paramdic['vardic'] = deepcopy(vardic)
    else:
        self.template_paramdic['vardic'] = False

    # Extract the model name and description
    if all([False if 'None' in x else True for x in secs['info'][0]]):
        for x in secs['info'][0]:
            if 'Name' in x:
                self.mod_name = x.split('=')[1].replace(';','').strip()
                # Save for template instantiation
                self.template_paramdic['mod_name'] = deepcopy(self.mod_name)          
            if 'Desc' in x:
                self.mod_desc = x.split('=')[1].replace(';','').strip()
                # Save for template instantiation
                self.template_paramdic['mod_desc'] = deepcopy(self.mod_desc)
        if not self.template_paramdic.has_key('mod_name'):
            self.template_paramdic['mod_name'] = False
        if not self.template_paramdic.has_key('mod_desc'):
            self.template_paramdic['mod_desc'] = False

    # Extract parameters into dictionary
    if all([False if 'None' in x else True for x in secs['params'][0]]):
        param = {}
        # need to do this so users don't have to worry about integer division
        # but preserves integer division for sympycore stuff
        safe_div = """
from __future__ import division
"""
        for x in secs['params'][0]:
            if ']' in x: x = x.split(']')[1].lstrip()
            list_tmp = x.split(';')
            list_tmp = list_tmp[0].split('=')[:]
            str_tmp1 = list_tmp[0].strip()
            str_tmp2 = list_tmp[1].strip()
            #NOTE: this *should* be safe, but users should know what's
            # in the .mod file
            exec(safe_div + "param['"+str_tmp1+"']=" + str_tmp2, {}, locals())
            locals()[str_tmp1] = param[str_tmp1]
        self.paramdic = param
        # Save for template instantiation
        self.template_paramdic['paramdic'] = deepcopy(param)
    else:
        self.template_paramdic['paramdic'] = False

    # Collect information on manual (closed-form) steady state
    if all([False if 'None' in x else True for x in secs['closedformss'][0]]):
        # Join multiline steady state definitions
        mansys = secs['closedformss'][0]
        list_tmp1 = []
        i1=0
        counter=0
        for x in mansys:
            if '...' in x:
                counter = counter + 1
            elif '...' not in x:
                if counter == 0:
                    # Just in case people have used [1] markers...
                    if ']' in x: x = x.split(']')[1].lstrip().rstrip()
                    list_tmp1.append(x)
                elif counter > 0:
                    str_tmp = ''
                    for y in mansys[i1-counter:i1+1]:
                        str_tmp = str_tmp + y.replace('...','')
                    # Just in case people have used [1] markers...
                    if ']' in str_tmp: str_tmp = str_tmp.split(']')[1].lstrip().rstrip()
                    list_tmp1.append(str_tmp)
                    counter = 0 
            i1=i1+1
        self.manss_sys = list_tmp1
        # Save for template instantiation
        self.template_paramdic['manss_sys'] = deepcopy(list_tmp1)
    else:
        self.template_paramdic['manss_sys'] = False
        
    # Collect info on numerical steady state
    if all([False if 'None' in x else True for x in secs['manualss'][0]]):
        _mreg_alt = '^\s*[a-zA-Z]*\d*_bar(?!=\+|-|\*|/])\s*=\s*.*'
        _mreg = '\[\d+\]\s*[a-zA-Z]*\d*_bar(?!=\+|-|\*|/])\s*=\s*.*'
        _mreg2 = '\[\d+\]\s*[a-zA-Z]*(?!=\+|-|\*|/])\s*=\s*[0-9]*\.[0-9]*'
        _mregfocs = 'USE_FOCS=\[.*?\]'
        mregfocs = re.compile(_mregfocs)
        use_focs = False
        for lino in secs['manualss'][0]:
            if mregfocs.search(lino):
                # Save as the list of equations the be used
                use_focs = eval(lino.split('=')[1].replace(';','').strip())
                self._internal_focs_used = True
        mreg = re.compile(_mreg_alt+'|'+_mreg+'|'+_mreg2)
        indx = []
        ssidic={}
        ssili = []
        list_tmp = []
        anyssi_found = False
        i1=0
        counter=0
        for x in secs['manualss'][0]:
            if mreg.search(x):
                raw_str = x.replace(';','')
                anyssi_found = True
                ma = mreg.search(raw_str)
                if ']' in ma.group(): str1 = ma.group().replace(';','').split('=')[0].split(']')[1].strip()
                else: str1 = ma.group().replace(';','').split('=')[0].lstrip().rstrip()
                str2 = ma.group().split('=')[1].strip()
                # Save the result as a string here, later in mk_mssidic_subs() method we do substitutions and evaluate then
                locals().update(self.paramdic)
                # This captures the case where we have only variables from parameters, but no substitutions
                if '@' not in str2:
                    ssidic[str1] = str(eval(str2))
                    locals()[str1] = eval(str2)
                else:
                    ssidic[str1] = str2
                ssili.append([str1,str2])
                indx.append(i1)
            elif not mreg.search(x) and '...' in x:
                counter = counter + 1
            elif not mreg.search(x) and '...' not in x:
                if counter == 0:
                    if ']' in x: list_tmp.append(x.replace(';','').split(']')[1].split('=')[0].strip())
                    else: list_tmp.append(x.replace(';','').split('=')[0].strip())
                elif counter > 0:
                    str_tmp = ''
                    for y in secs['manualss'][0][i1-counter:i1+1]:
                        str_tmp = str_tmp + y.replace('...','').strip()
                    if ']' in str_tmp: list_tmp.append(str_tmp.split(']')[1].split('=')[0].replace(';','').strip())
                    else: list_tmp.append(str_tmp.split('=')[0].replace(';','').strip())
                    counter = 0 
            i1=i1+1
        if anyssi_found:
            self.ssidic = deepcopy(ssidic)
            self.ssili = deepcopy(ssili)
            # Save for template instantiation
            self.template_paramdic['ssidic'] = deepcopy(ssidic)            
        else:
            #Make empty to be filled by other procedure
            self.ssidic = {}
            self.ssili = []
            # Save for template instantiation
            self.template_paramdic['ssidic'] = False

        if not use_focs:
            self.ssys_list = deepcopy(list_tmp) 
            # Save for template instantiation
            self.template_paramdic['ssys_list'] = deepcopy(list_tmp)
            self.template_paramdic['use_focs'] = False
        elif use_focs and anyssi_found:
            self._use_focs = deepcopy(use_focs)
            self._ssidic = deepcopy(ssidic)
            self.ssili = deepcopy(ssili)
            # Save for template instantiation
            self.template_paramdic['ssys_list'] = False
            self.template_paramdic['use_focs'] = deepcopy(use_focs)
        elif use_focs and not anyssi_found:
            self._use_focs = deepcopy(use_focs)
            # Save for template instantiation
            self.template_paramdic['ssys_list'] = False
            self.template_paramdic['use_focs'] = deepcopy(use_focs)
            
    else:
        # Save for template instantiation
        self.template_paramdic['ssidic'] = False       
        self.template_paramdic['ssys_list'] = False
        self.template_paramdic['use_focs'] = False
        
    return self


############# BELOW HERE IS ALL FOR 2ND STAGE ###########
def def_timing(self,exo=[-1,0],endo=[-1,0],con=[0,1]):
    '''
    A small method which can be used in order to set the timings in stone.
    This will then be used in other parts of the code, also in macrolab package
    '''
    self.vtiming = {}
    self.vtiming['endo'] = deepcopy(endo)
    self.vtiming['exo'] = deepcopy(exo)
    self.vtiming['con'] = deepcopy(con)
    
    return self

def mkaug2(self,insys=None,othersys=None):

    # Timing definitions
    endotime = self.vtiming['endo']
    exotime = self.vtiming['exo']
    contime = self.vtiming['con']
    endosp = []
    for x in self.vardic['endo']['var']:
        endosp = endosp + [[x,deepcopy(endotime)]]
    exosp = []
    for x in self.vardic['exo']['var']:
        exosp = exosp + [[x,deepcopy(exotime)]]
    consp = []
    for x in self.vardic['con']['var']:
        consp = consp + [[x,deepcopy(contime)]]

    alldic = {}
    alldic.update(self.paramdic)
    alldic.update(self.sstate)

    spvdic = {}
    spvdic['endo'] = endosp
    spvdic['exo'] = exosp
    spvdic['con'] = consp

    spvdic2 = deepcopy(spvdic)

    spvdic3 = deepcopy(spvdic2)
    spvdic3['endo'] = {}
    spvdic3['con'] = {}
    spvdic3['exo'] = {}

    endoli = [x[0].split('(')[0].strip() for x in self.vardic['endo']['var']]
    exoli = [x[0].split('(')[0].strip() for x in self.vardic['exo']['var']]
    conli = [x[0].split('(')[0].strip() for x in self.vardic['con']['var']]


    patup = ('{-100,100}|None','all','{-100,100}')
    count = 0
    
    list_tmp1 = deepcopy(insys)
    for i1,line in enumerate(list_tmp1):
        iterob = self.vreg(patup,line,True,'max')
        if iterob:
            iterob = list(iterob)
        else:
            continue
        iterob.reverse()
        for vma in iterob:
            vtype = vma[1][0]
            vartime = vma[2][2]
            vari = vma[2][1]
            pos = vma[3][0]
            poe = vma[3][1]
            
            # In the following section we will replace time-shifted variables with their auxiliary counterparts
            # in the EXISTING equations of the FOCs, but no new definitions of auxiliary variables are being added
            # Depending on options passed, we may work on the FOCs or the items in NLSUBS_LIST
            if vtype == 'endo':
                indx = endoli.index(vari)
                if not spvdic3['endo'].has_key(vari):
                    spvdic3['endo'][vari] = []
                if spvdic3['endo'][vari] == []:
                    spvdic3['endo'][vari].append(int(vartime))
                    spvdic3['endo'][vari].append(int(vartime))
                elif int(vartime) < spvdic3['endo'][vari][0]: spvdic3['endo'][vari][0] = int(vartime)
                elif int(vartime) > spvdic3['endo'][vari][1]: spvdic3['endo'][vari][1] = int(vartime)
            elif vtype == 'con':
                indx = conli.index(vari)
                if not spvdic3['con'].has_key(vari):
                    spvdic3['con'][vari] = []
                if spvdic3['con'][vari] == []:
                    spvdic3['con'][vari].append(int(vartime))
                    spvdic3['con'][vari].append(int(vartime))
                elif int(vartime) < spvdic3['con'][vari][0]: spvdic3['con'][vari][0] = int(vartime)
                elif int(vartime) > spvdic3['con'][vari][1]: spvdic3['con'][vari][1] = int(vartime)
            elif vtype == 'exo':
                indx = exoli.index(vari)
                if not spvdic3['exo'].has_key(vari):
                    spvdic3['exo'][vari] = []
                if spvdic3['exo'][vari] == []:
                    spvdic3['exo'][vari].append(int(vartime))
                    spvdic3['exo'][vari].append(int(vartime))
                elif int(vartime) < spvdic3['exo'][vari][0]: spvdic3['exo'][vari][0] = int(vartime)
                elif int(vartime) > spvdic3['exo'][vari][1]: spvdic3['exo'][vari][1] = int(vartime)
            else:
                continue

            # Check for endo
            if vtype == 'endo' and int(vartime) > spvdic['endo'][indx][1][1]:
                spvdic2['endo'][indx][1][1] = int(vartime)
                tind = (5-len(str(abs(endotime[1]-int(vartime)))))*'0'+str(abs(endotime[1]-int(vartime)))
                newvar = vari+'_F'+tind+'(t)'
                newname =  vari+'_F'+str(abs(endotime[1]-int(vartime)))
                list_tmp1[i1] = list_tmp1[i1][:pos]+newvar.split('(')[0]+'(t)'+list_tmp1[i1][poe:]
                for i2 in range(abs(int(vartime)-spvdic['endo'][indx][1][1])):
                    tind = (5-len(str(abs(i2+1))))*'0'+str(abs(i2+1))
                    newvar = vari+'_F'+tind+'(t)'
                    newname =  vari+'_F'+str(abs(i2+1))
                    if [newvar,newname] not in self.vardic['con']['var']:
                        self.vardic['con']['var'].append([newvar,newname])
                        self.vardic['con']['mod'].append(self.vardic['endo']['mod'][indx])
                        self.audic['con']['var'].append([newvar,newname])
                        self.audic['con']['mod'].append(self.vardic['endo']['mod'][indx])
                        if self.sstate.has_key(vari+'_bar'):
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.sstate[vari+'_bar']
                        else:
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.paramdic[vari+'_bar']
                    continue
            elif vtype == 'endo' and int(vartime) < spvdic['endo'][indx][1][0]:
                spvdic2['endo'][indx][1][0] = int(vartime)
                tind = (5-len(str(abs(endotime[0]-int(vartime)))))*'0'+str(abs(endotime[0]-int(vartime)))
                newvar = vari+'_B'+tind+'(t)'
                newname =  vari+'_B'+str(abs(endotime[0]-int(vartime)))
                list_tmp1[i1] = list_tmp1[i1][:pos]+newvar.split('(')[0]+'(t-1)'+list_tmp1[i1][poe:]
                for i2 in range(1,abs(int(vartime)-spvdic['endo'][indx][1][0])+1):
                    tind = (5-len(str(abs(i2))))*'0'+str(abs(i2))
                    newvar = vari+'_B'+tind+'(t)'
                    newname =  vari+'_B'+str(abs(i2))
                    if [newvar,newname] not in self.vardic['endo']['var']:
                        self.vardic['endo']['var'].append([newvar,newname])
                        self.vardic['endo']['mod'].append(self.vardic['endo']['mod'][indx])
                        self.audic['endo']['var'].append([newvar,newname])
                        self.audic['endo']['mod'].append(self.vardic['endo']['mod'][indx])
                        if self.sstate.has_key(vari+'_bar'):
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.sstate[vari+'_bar']
                        else:
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.paramdic[vari+'_bar']
                    continue

            # Check for exo
            if vtype == 'exo' and int(vartime) > spvdic['exo'][indx][1][1]:
                spvdic2['exo'][indx][1][1] = int(vartime)
                tind = (5-len(str(abs(exotime[1]-int(vartime)))))*'0'+str(abs(exotime[1]-int(vartime)))
                newvar = vari+'_F'+tind+'(t)'
                newname =  vari+'_F'+str(abs(exotime[1]-int(vartime)))
                list_tmp1[i1] = list_tmp1[i1][:pos]+newvar.split('(')[0]+'(t)'+list_tmp1[i1][poe:]
                for i2 in range(abs(int(vartime)-spvdic['exo'][indx][1][1])):
                    tind = (5-len(str(abs(i2+2)-1)))*'0'+str(abs(i2+2)-1)
                    newvar = vari+'_F'+tind+'(t)'
                    newname =  vari+'_F'+str(abs(i2+1))
                    if [newvar,newname] not in self.vardic['con']['var']:
                        self.vardic['con']['var'].append([newvar,newname])
                        self.vardic['con']['mod'].append(self.vardic['exo']['mod'][indx])
                        self.audic['con']['var'].append([newvar,newname])
                        self.audic['con']['mod'].append(self.vardic['exo']['mod'][indx])
                        if self.sstate.has_key(vari+'_bar'):
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.sstate[vari+'_bar']
                        else:
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.paramdic[vari+'_bar']
                    continue
            elif vtype == 'exo' and int(vartime) < spvdic['exo'][indx][1][0]:
                spvdic2['exo'][indx][1][0] = int(vartime)
                tind = (5-len(str(abs(exotime[0]-int(vartime)))))*'0'+str(abs(exotime[0]-int(vartime)))
                newvar = vari+'_B'+tind+'(t)'
                newname =  vari+'_B'+str(abs(exotime[0]-int(vartime)))
                list_tmp1[i1] = list_tmp1[i1][:pos]+newvar.split('(')[0]+'(t-1)'+list_tmp1[i1][poe:]
                for i2 in range(abs(int(vartime)-spvdic['exo'][indx][1][0])):
                    tind = (5-len(str(abs(i2+2)-1)))*'0'+str(abs(i2+2)-1)
                    newvar = vari+'_B'+tind+'(t)'
                    newname =  vari+'_B'+str(abs(i2+1))
                    if [newvar,newname] not in self.vardic['endo']['var']:
                        self.vardic['endo']['var'].append([newvar,newname])
                        self.vardic['endo']['mod'].append(self.vardic['exo']['mod'][indx])
                        self.audic['endo']['var'].append([newvar,newname])
                        self.audic['endo']['mod'].append(self.vardic['exo']['mod'][indx])
                        if self.sstate.has_key(vari+'_bar'):
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.sstate[vari+'_bar']
                        else:
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.paramdic[vari+'_bar']
                    continue
            # Check for con
            if vtype == 'con' and int(vartime) > spvdic['con'][indx][1][1]:
                spvdic2['con'][indx][1][1] = int(vartime)
                tind = (5-len(str(abs(contime[1]-int(vartime)))))*'0'+str(abs(contime[1]-int(vartime)))
                newvar = vari+'_F'+tind+'(t)'
                newname =  vari+'_F'+str(abs(contime[1]-int(vartime)))
                list_tmp1[i1] = list_tmp1[i1][:pos]+newvar.split('(')[0]+'(t)'+list_tmp1[i1][poe:]
                for i2 in range(abs(int(vartime)-spvdic['con'][indx][1][1])):
                    tind = (5-len(str(abs(i2+2)-1)))*'0'+str(abs(i2+2)-1)
                    newvar = vari+'_F'+tind+'(t)'
                    newname =  vari+'_F'+str(abs(i2+1))
                    if [newvar,newname] not in self.vardic['con']['var']:
                        self.vardic['con']['var'].append([newvar,newname])
                        self.vardic['con']['mod'].append(self.vardic['con']['mod'][indx])
                        self.audic['con']['var'].append([newvar,newname])
                        self.audic['con']['mod'].append(self.vardic['con']['mod'][indx])
                        if self.sstate.has_key(vari+'_bar'):
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.sstate[vari+'_bar']
                        else:
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.paramdic[vari+'_bar']
                    continue
            elif vtype == 'con' and int(vartime) < spvdic['con'][indx][1][0] and spvdic3['con'][vari][0] < contime[0]:
                spvdic2['con'][indx][1][0] = int(vartime)
                tind = (5-len(str(abs(contime[0]-int(vartime)))))*'0'+str(abs(contime[0]-int(vartime)))
                newvar = vari+'_B'+tind+'(t)'
                newname =  vari+'_B'+str(abs(contime[0]-int(vartime)))
                list_tmp1[i1] = list_tmp1[i1][:pos]+newvar.split('(')[0]+'(t-1)'+list_tmp1[i1][poe:]
                for i2 in range(abs(int(vartime)-spvdic['con'][indx][1][0])):
                    tind = (5-len(str(abs(i2+2)-1)))*'0'+str(abs(i2+2)-1)
                    newvar = vari+'_B'+tind+'(t)'
                    newname =  vari+'_B'+str(abs(i2+1))
                    if [newvar,newname] not in self.vardic['endo']['var']:
                        self.vardic['endo']['var'].append([newvar,newname])
                        self.vardic['endo']['mod'].append(self.vardic['con']['mod'][indx])
                        self.audic['endo']['var'].append([newvar,newname])
                        self.audic['endo']['mod'].append(self.vardic['con']['mod'][indx])
                        if self.sstate.has_key(vari+'_bar'):
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.sstate[vari+'_bar']
                        else:
                            self.sstate[newvar.split('(')[0]+'_bar'] = self.paramdic[vari+'_bar']
                    continue

    # Save the timings which were found in the FOC equations, or update exisiting one
    if 'vtimings_found' not in dir(self):
        self.vtimings_found = deepcopy(spvdic3)
        self.vtimings_differ = deepcopy(self.vtimings_found)
    else:
        for keyo in spvdic3.keys():
            for keyo2 in spvdic3[keyo].keys():
                if spvdic3[keyo][keyo2][0] < self.vtimings_found[keyo][keyo2][0]:
                    self.vtimings_found[keyo][keyo2][0] = spvdic3[keyo][keyo2][0]
                if spvdic3[keyo][keyo2][1] > self.vtimings_found[keyo][keyo2][1]:
                    self.vtimings_found[keyo][keyo2][1] = spvdic3[keyo][keyo2][1]
    # Also add a second dictionary which shows the difference between what was found and the reference timing
    for keyo in self.vtimings_found.keys():
        for keyo2 in self.vtimings_found[keyo].keys():
            if keyo == 'endo': self.vtimings_differ[keyo][keyo2] =\
               list([x for x in np.array(self.vtimings_found[keyo][keyo2]) - np.array(endotime)])
            elif keyo == 'exo': self.vtimings_differ[keyo][keyo2] =\
               list([x for x in np.array(self.vtimings_found[keyo][keyo2]) - np.array(exotime)])
            elif keyo == 'con': self.vtimings_differ[keyo][keyo2] =\
               list([x for x in np.array(self.vtimings_found[keyo][keyo2]) - np.array(contime)])
                

    #################################################################################################
    ##
    ## In this section we will compute the declarations which have to be added to the nonlinear system
    ## in order to incorporate and include in derivations the auxiliare variables used throughout
    ##
    #################################################################################################
    list_added = []
    # Now change the system to include possible augmented variables
    endo_r = filter(lambda x: x[1] != endotime, spvdic2['endo'])
    if endo_r:
        endo_r = [[x[0],[abs(x[1][0]-endotime[0]),abs(x[1][1]-endotime[1])]] for x in endo_r ]
        # Create lags and forwards equations
        for vari in endo_r:
            varin = vari[0][0].split('(')[0]
            if vari[1][0] != 0:
                lagor = range(abs(spvdic3['endo'][varin][0]-endotime[0]))
                for lag in lagor:
                    
                    # Define some indices to be used
                    tindm1 = (5-len(str(lead-1)))*'0'+str(lead-1)
                    tind = (5-len(str(lead)))*'0'+str(lead)
                    tind1 = (5-len(str(lead+1)))*'0'+str(lead+1)
                    tind2 = (5-len(str(lead+2)))*'0'+str(lead+2)
                    
                    # Define the beginning definition, needs to link up with the last variable define in endotime[1]
                    if lag == lagor[0]:
                        lag_endo_diff = spvdic3['endo'][varin][0]-endotime[0]
                        if lag_endo_diff < 0:
                            list_added.append(varin+'(t-'+str(abs(lag_endo_diff))+')'+' - '+varin+'_B00001(t-1)')
                            if lag_endo_diff+1 > 0: list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'(t+'+str(lag_endo_diff-1)+')')
                            elif lag_endo_diff+1 == 0: list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'(t)')
                            elif lag_endo_diff+1 < 0: list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'(t-'+str(abs(lag_endo_diff-1))+')')
                        elif lag_endo_diff == 0:
                            list_added.append(varin+'(t)'+' - '+varin+'_B00001(t-1)')
                            if lag_endo_diff-1 > 0: list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'(t+'+str(lag_endo_diff-1)+')')
                            elif lag_endo_diff-1 == 0: list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'(t)')
                            elif lag_endo_diff-1 < 0: list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'(t-'+str(abs(lag_endo_diff-1))+')')                                        
                        elif lag_endo_diff > 0:
                            list_added.append(varin+'(t+'+str(lag_endo_diff)+')'+' - '+varin+'_B00001(t-1)')
                            if lag_endo_diff-1 > 0: list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'(t+'+str(lag_endo_diff-1)+')')
                            elif lag_endo_diff-1 == 0: list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'(t)')
                            elif lag_endo_diff-1 < 0: list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'(t-'+str(abs(lag_endo_diff-1))+')')
                        if varin+'_B'+tind1+'(t)'+' - '+varin+'_B'+tind+'(t-1)' not in list_added:
                            list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'_B'+tind+'(t-1)')
                            
                    # For in between
                    if lag != lagor[0] and lag != lagor[-1]:
                        expro = varin+'_B'+tind+'(t)'+' - '+varin+'_B'+tindm1+'(t-1)'
                        if expro not in list_added:
                            list_added.append(expro)

                    # Define the end tail definition
                    if lag == lagor[-1] and len(lagor) != 1:  
                        if varin+'_B'+tind+'(t)'+' - '+varin+'_B'+tindm1+'(t-1)' not in list_added:
                            list_added.append(varin+'_B'+tind+'(t)'+' - '+varin+'_B'+tindm1+'(t-1)')
                        if varin+'_B'+tind1+'(t)'+' - '+varin+'_B'+tind+'(t-1)' not in list_added:
                            list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'_B'+tind+'(t-1)')
                    

            leador = range(abs(spvdic3['endo'][varin][1]-endotime[1]))
            if vari[1][1] != 0:
                for lead in leador:
                    
                    # Define some indices to be used
                    tindm1 = (5-len(str(lead-1)))*'0'+str(lead-1)
                    tind = (5-len(str(lead)))*'0'+str(lead)
                    tind1 = (5-len(str(lead+1)))*'0'+str(lead+1)
                    tind2 = (5-len(str(lead+2)))*'0'+str(lead+2)
                    
                    # Define the beginning definition, needs to link up with the last variable define in endotime[1]
                    if lead == leador[0]:
                        if endotime[1] < 0:
                            list_added.append(varin+'(t'+str(endotime[1])+')'+' - '+varin+'_F00001(t-1)')
                        elif endotime[1] == 0:
                            list_added.append(varin+'(t)'+' - '+varin+'_F00001(t-1)')
                        elif endotime[1] > 0:
                            list_added.append(varin+'(t+'+str(endotime[1])+')'+' - '+varin+'_F00001(t-1)')
                        if endotime[1]+1 < 0:
                            list_added.append(varin+'_F'+tind+'(t)'+' - '+varin+'(t-'+str(abs(endotime[1]+1))+')')
                        elif endotime[1]+1 == 0:
                            list_added.append(varin+'_F'+tind+'(t)'+' - '+varin+'(t)')
                        elif endotime[1]+1 > 0:
                            list_added.append(varin+'_F'+tind+'(t)'+' - '+varin+'(t+'+str(abs(endotime[1]+1))+')')
                                
                    # For in between
                    if lead != leador[0] and lead != leador[-1]:
                        if varin+'_F'+tind+'(t)'+' - '+varin+'_F'+tind1+'(t-1)' not in list_added:
                            list_added.append(varin+'_F'+tind+'(t)'+' - '+varin+'_F'+tind1+'(t-1)')
                        
                    # Define the end tail definition
                    if lead == leador[-1] and len(leador) != 1:
                        if spvdic3['endo'][varin][1] > 0:
                            list_added.append(varin+'_F'+tind+'(t)'+' - '+varin+'(t+'+str(spvdic3['endo'][varin][1])+')')
                        elif spvdic3['endo'][varin][1] == 0:
                            list_added.append(varin+'_F'+tind+'(t)'+' - '+varin+'(t)')
                        elif spvdic3['endo'][varin][1] < 0:
                            list_added.append(varin+'_F'+tind+'(t)'+' - '+varin+'(t-'+str(abs(spvdic3['endo'][varin][1]))+')')  

    exo_r = filter(lambda x: x[1] != exotime, spvdic2['exo'])
    if exo_r:
        exo_r = [[x[0],[abs(x[1][0])-abs(exotime[0]),x[1][1]-abs(exotime[1])]] for x in exo_r ]
        # Create lags and forwards equations
        for vari in exo_r:
            varin = vari[0][0].split('(')[0]
            if vari[1][0] != 0:
                abstdiffer = abs(spvdic3['exo'][varin][0]-exotime[0])
                lagor = range(abstdiffer)
                for lag in lagor:
                    
                    # Define some indices to be used
                    tindm1 = (5-len(str(lag-1)))*'0'+str(lag-1)
                    tind = (5-len(str(lag)))*'0'+str(lag)
                    tind1 = (5-len(str(lag+1)))*'0'+str(lag+1)
                    tind2 = (5-len(str(lag+2)))*'0'+str(lag+2)
                    
                    # Define the beginning definition, needs to link up with the last variable define in exotime[1]
                    if lag == lagor[0]:
                        lag_exo_diff = spvdic3['exo'][varin][0]-exotime[0]
                        timor = spvdic3['exo'][varin][0]+exotime[0]
                        if lag_exo_diff < 0:
                            if timor > 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(timor)+')')
                            elif timor == 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t)')
                            elif timor < 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(timor))+')')
                        elif lag_exo_diff == 0:
                            if timor > 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(timor)+')')
                            elif timor == 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t)')
                            elif timor < 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(timor))+')')                                        
                        elif lag_exo_diff > 0:
                            if timor > 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(timor)+')')
                            elif timor == 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t)')
                            elif timor < 0: list_added.append(+'_B'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(timor))+')')
                            
                    # For in between
                    if lag != lagor[0] and lag != lagor[-1] and len(lagor) != 1:
                        expro = varin+'_B'+tind+'(t)'+' - '+varin+'_B'+tindm1+'(t-1)'
                        if expro not in list_added:
                            list_added.append(expro)

                    # Define the end tail definition
                    if lag == lagor[-1] and len(lagor) != 1:  
                        if varin+'_B'+tind1+'(t)'+' - '+varin+'_B'+tind+'(t-1)' not in list_added:
                            list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'_B'+tind+'(t-1)')
            
            abstdiffer = abs(spvdic3['exo'][varin][1]-exotime[1])       
            leador = range(abstdiffer)
            if vari[1][1] != 0:
                for lead in leador:
                    
                    # Define some indices to be used
                    tindm1 = (5-len(str(lead-1)))*'0'+str(lead-1)
                    tind = (5-len(str(lead)))*'0'+str(lead)
                    tind1 = (5-len(str(lead+1)))*'0'+str(lead+1)
                    tind2 = (5-len(str(lead+2)))*'0'+str(lead+2)
                    
                    # Define the beginning definition, needs to link up with the last variable define in endotime[1]
                    if lead == leador[0]:
                        if exotime[1]+1 < 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(exotime[1]+1))+')')
                        elif exotime[1]+1 == 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'(t)')
                        elif exotime[1]+1 > 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(abs(exotime[1]+1))+')')
                                
                    # For in between
                    if lead != leador[0] and lead != leador[-1]:
                        if varin+'_F'+tind1+'(t)'+' - '+varin+'_F'+tind2+'(t-1)' not in list_added:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'_F'+tind2+'(t-1)')
                        
                    # Define the end tail definition
                    if lead == leador[-1] and len(leador) != 1:
                        if spvdic3['exo'][varin][1] > 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(spvdic3['exo'][varin][1])+')')
                        elif spvdic3['exo'][varin][1] == 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'(t)')
                        elif spvdic3['exo'][varin][1] < 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(spvdic3['exo'][varin][1]))+')')
                            
    con_r = filter(lambda x: x[1] != contime, spvdic2['con'])
    if con_r:
        con_r = [[x[0],[abs(x[1][0])-abs(contime[0]),x[1][1]-abs(contime[1])]] for x in con_r ]
        # Create lags and forwards equations
        for vari in con_r:
            varin = vari[0][0].split('(')[0]
            if vari[1][0] != 0:
                abstdiffer = abs(spvdic3['con'][varin][0]-contime[0])
                lagor = range(abstdiffer)
                for lag in lagor:
                    
                    # Define some indices to be used
                    tindm1 = (5-len(str(lag-1)))*'0'+str(lag-1)
                    tind = (5-len(str(lag)))*'0'+str(lag)
                    tind1 = (5-len(str(lag+1)))*'0'+str(lag+1)
                    tind2 = (5-len(str(lag+2)))*'0'+str(lag+2)
                    
                    # Define the beginning definition, needs to link up with the last variable define in contime[1]
                    if lag == lagor[0]:
                        lag_con_diff = spvdic3['con'][varin][0]-contime[0]
                        timor = spvdic3['con'][varin][0]+contime[0]+1
                        if lag_con_diff < 0:
                            if timor > 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(timor)+')')
                            elif timor == 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t)')
                            elif timor < 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(timor))+')')
                        elif lag_con_diff == 0:
                            if timor > 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(timor)+')')
                            elif timor == 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t)')
                            elif timor < 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(timor))+')')                                        
                        elif lag_con_diff > 0:
                            if timor > 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(timor)+')')
                            elif timor == 0: list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'(t)')
                            elif timor < 0: list_added.append(+'_B'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(timor))+')')
                            
                    # For in between
                    if lag != lagor[0] and lag != lagor[-1] and len(lagor) != 1:
                        expro = varin+'_B'+tind+'(t)'+' - '+varin+'_B'+tindm1+'(t-1)'
                        if expro not in list_added:
                            list_added.append(expro)

                    # Define the end tail definition
                    if lag == lagor[-1] and len(lagor) != 1:  
                        if varin+'_B'+tind1+'(t)'+' - '+varin+'_B'+tind+'(t-1)' not in list_added:
                            list_added.append(varin+'_B'+tind1+'(t)'+' - '+varin+'_B'+tind+'(t-1)')
            
            abstdiffer = abs(spvdic3['con'][varin][1]-contime[1])       
            leador = range(abstdiffer)
            if vari[1][1] != 0:
                for lead in leador:
                    
                    # Define some indices to be used
                    tindm1 = (5-len(str(lead-1)))*'0'+str(lead-1)
                    tind = (5-len(str(lead)))*'0'+str(lead)
                    tind1 = (5-len(str(lead+1)))*'0'+str(lead+1)
                    tind2 = (5-len(str(lead+2)))*'0'+str(lead+2)
                    
                    
                    # Define the beginning definition, needs to link up with the last variable define in endotime[1]
                    if lead == leador[0]:
                        if contime[1]+1 < 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(contime[1]+1))+')')
                        elif contime[1]+1 == 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'(t)')
                        elif contime[1]+1 > 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(abs(contime[1]+1))+')')
                                
                    # For in between
                    if lead != leador[0] and lead != leador[-1]:
                        if varin+'_F'+tind1+'(t)'+' - '+varin+'_F'+tind2+'(t-1)' not in list_added:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'_F'+tind2+'(t-1)')
                        
                    # Define the end tail definition
                    if lead == leador[-1] and len(leador) != 1:
                        if spvdic3['con'][varin][1] > 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+'E(t)|'+varin+'(t+'+str(spvdic3['con'][varin][1])+')')
                        elif spvdic3['con'][varin][1] == 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'(t)')
                        elif spvdic3['con'][varin][1] < 0:
                            list_added.append(varin+'_F'+tind1+'(t)'+' - '+varin+'(t-'+str(abs(spvdic3['con'][varin][1]))+')')

    # If only on system was passed in then we just return the modified equations with the added equations attached at bottom
    # If two systems were passed, then we return the substituted out system of equations (in nlsubs_list) and the declarations added
    # to the bottom of the usual FOC system of equations, BUT ONLY if they are not already included
    if othersys == None:
        for lino in list_added:
            if lino not in list_tmp1: list_tmp1.append(lino)
        return self, deepcopy(list_tmp1)
    elif othersys != None:
        for lino in list_added:
            if lino not in othersys:
                othersys.append(lino)
        return self, (list_tmp1,othersys)


def mk_subs_dic(self, secs):
    # Make the substitution system by joining lines and stripping
    list_tmp2 = []
    # This list is used to catch the @ALL instructions and store them
    list_tmp3 = []
    list_tmp3_ind = []
    # A list which collects all elements, to be handed to the template_paramdic for template parsing
    list_tmp4 = []
    i1=0
    linecounter=0
    for x in secs['vsfocs'][0]:
        if x.endswith(("...","\\")):
            linecounter += 1
        else:
            if linecounter == 0:
                ################# Catch @ALL expressions and store################
                if "@ALL" in x:
                    intor = []
                    intor1 = x.split('@ALL')[1].replace(';','')
                    intor.append('@ALL')
                    intor.append(intor1)
                    list_tmp4.append(intor)
                    raw_str = x.split(';')[0].split('@ALL')[1].split('{')[1].split('}')[0]
                    list_tmp3.append(raw_str.split(','))
                    list_tmp3_ind.append(i1)
                    continue
                ##################################################################
                line = x.replace(';','').split(']')[1].strip()
            elif linecounter > 0: # have a multiline equation
                str_tmp = ''
                for y in secs['vsfocs'][0][i1-linecounter:i1+1]:
                    str_tmp += y.replace('...','').replace(';','').replace('//','').strip()
                ################# Catch @ALL expressions and store################
                if "@ALL" in str_tmp:
                    intor = []
                    intor1 = x.split('@ALL')[1].replace(';','')
                    intor.append('@ALL')
                    intor.append(intor1)
                    list_tmp4.append(intor)
                    raw_str = str_tmp.split('@ALL')[1].split('{')[1].split('}')[0]
                    list_tmp3.append(raw_str.split(','))
                    list_tmp3_ind.append(i1)
                    continue
                ##################################################################
                if ']' in str_tmp:
                    line = str_tmp.split(']')[1].strip()
                else:
                    line = str_tmp.strip()
                linecounter = 0 
        i1 += 1
        splitline = line.split('=')
        # Only consider the first split of = found, this is used because of subs_ind
        if len(splitline) > 2:
            tmpstr = ''
            for elem in splitline[1:]:
                tmpstr = tmpstr+'='+elem
            tmpstr = tmpstr[1:]
            splitline = [splitline[0],tmpstr]
        list_tmp4.append([splitline[0].strip(), splitline[1].strip()])
        list_tmp2.append([splitline[0].strip(), splitline[1].strip()])
    self.allsubs_raw1 = deepcopy(list_tmp3)
    self.allsubs_index = deepcopy(list_tmp3_ind)
    self.nlsubs_raw1 = deepcopy(list_tmp2)
    self.nlsubsdic = dict(list_tmp2)
    if list_tmp4 != []: self.template_paramdic['subs_list'] = deepcopy(list_tmp4)
    else: self.template_paramdic['subs_list'] = False
    return self

def subs_in_subs_all(self):
    list_tmp3 = deepcopy(self.allsubs_raw1)
    list_tmp2 = deepcopy(self.nlsubs_raw1)
    # Replace substitutions inside substitutions, for both time-subscripted and steady state vars!
    mreg = re.compile('@DISCOUNT|@(E\(t.*?\)\|){0,1}.*?\(t.*?\)|@(E\(t.*?\)\|){0,1}.*?_bar')
    variables = [x[0] for x in list_tmp2] # do this once
    for i,x in enumerate(list_tmp3):
        expr = list_tmp3[i][0]
        while mreg.search(expr):
            ma = mreg.search(expr)
            indx = variables.index(ma.group())
            expr = list_tmp2[indx][1]
            list_tmp3[i][0] = expr
    self.allsubs_raw2 = deepcopy(list_tmp3)
    return self

def mk_all(self):
    list_tmp1 = deepcopy(self.allsubs_raw2)
    list_tmp2 = deepcopy(self.allsubs_raw1)
    list_tmp3 = deepcopy(self.nlsubs_raw1)
    subsli = [x[0] for x in list_tmp3]
    repldic_li = []
    do_ss = False
    for i1,elem in enumerate(list_tmp1):
        repldic = {}
        if 'SS' in elem: do_ss = True
        stem = list_tmp2[i1][0].split('(')[0]
        stem_time = '('+list_tmp2[i1][0].split('(')[1]
        # Do the simplest SS conversion
        if stem+'_bar' not in subsli: repldic[stem+'_bar'] = 'SS{'+stem+stem_time+'}'
        if '-' in elem[1]:
            chron = range(int(elem[1].split('-')[0].split('[')[1]),int(elem[1].split('-')[1].split(']')[0])+1)
        else:
            chron = elem[2].split('[')[1].split(']')[0].split(',')
            chron = [int(x) for x in chron]
        # Do current-period differentiation and SS jobs first
        patup = ('{-10,10}|None','endo|con|exo|other','{-10,10}')
        varli = self.vreg(patup,list_tmp1[i1][0],True,'max')
        for chrono in chron:
            if chrono == 0:
                for varo in varli:
                    if varo[1][0] == 'con' and int(varo[2][2]) == 0:
                        if stem+varo[2][1]+stem_time not in subsli:
                            repldic[stem+varo[2][1]+stem_time] = 'DIFF{'+stem+stem_time+','+varo[0]+'}'
                        if stem+varo[2][1]+'_bar' not in subsli:
                            repldic[stem+varo[2][1]+'_bar'] = 'SS{'+stem+varo[2][1]+stem_time+'}'
                    elif varo[1][0] == 'endo' and int(varo[2][2]) == -1:
                        if stem+varo[2][1]+stem_time not in subsli:
                            repldic[stem+varo[2][1]+stem_time] = 'DIFF{'+stem+stem_time+','+varo[0]+'}'
                        if stem+varo[2][1]+'_bar' not in subsli:
                            repldic[stem+varo[2][1]+'_bar'] = 'SS{'+stem+varo[2][1]+stem_time+'}'
            else:
                if stem_time == '(t)':
                    stem_time_new = '(t+'+str(chrono)+')'
                elif '+' in stem_time:
                    old_t = int(stem_time.split('+')[1].split(')')[0])
                    stem_time_new = '(t+'+str(old_t+chrono)+')'
                elif '-' in stem_time:
                    old_t = int('-'+stem_time.split('-')[1].split(')')[0])
                    stem_time_new = '(t+'+str(old_t+chrono)+')'
                for varo in varli:
                    if chrono > 0:
                        if varo[1][0] == 'con' and int(varo[2][2]) == 0:
                            if stem+stem_time_new not in subsli:
                                repldic[stem+stem_time_new] = 'FF_'+str(chrono)+'{'+stem+stem_time+'}'
                            if stem+varo[2][1]+stem_time_new not in subsli:
                                repldic[stem+varo[2][1]+stem_time_new] = 'DIFF{'+stem+stem_time_new+','+'FF_'+str(chrono)+'{'+varo[0]+'}'+'}'
                        elif varo[1][0] == 'endo' and int(varo[2][2]) == -1:
                            if stem+stem_time_new not in subsli:
                                repldic[stem+stem_time_new] = 'FF_'+str(chrono)+'{'+stem+stem_time+'}'
                            if stem+varo[2][1]+stem_time_new not in subsli:
                                repldic[stem+varo[2][1]+stem_time_new] = 'DIFF{'+stem+stem_time_new+','+'FF_'+str(chrono)+'{'+varo[0]+'}'+'}'
                    elif chrono < 0:
                        if varo[1][0] == 'con' and int(varo[2][2]) == 0:
                            if stem+stem_time_new not in subsli:
                                repldic[stem+stem_time_new] = 'BB_'+str(abs(chrono))+'{'+stem+stem_time+'}'
                            if stem+varo[2][1]+stem_time_new not in subsli:
                                repldic[stem+varo[2][1]+stem_time_new] = 'DIFF{'+stem+stem_time_new+','+'BB_'+str((chrono))+'{'+varo[0]+'}'+'}'
                        elif varo[1][0] == 'endo' and int(varo[2][2]) == -1:
                            if stem+stem_time_new not in subsli:
                                repldic[stem+stem_time_new] = 'BB_'+str(abs(chrono))+'{'+stem+stem_time+'}'
                            if stem+varo[2][1]+stem_time_new not in subsli:
                                repldic[stem+varo[2][1]+stem_time_new] = 'DIFF{'+stem+stem_time_new+','+'BB_'+str(abs(chrono))+'{'+varo[0]+'}'+'}'
        repldic_li.append(repldic)
    repldic_li.reverse()
    indexli = deepcopy(self.allsubs_index)
    indexli.reverse()
    for i1,indexo in enumerate(indexli):
        self.nlsubs_raw1 = self.nlsubs_raw1[:indexo]+[list(x) for x in repldic_li[i1].items()]+self.nlsubs_raw1[indexo:]
    del self.allsubs_index
    return self
                
            
            

def subs_in_subs(self):
    list_tmp2 = deepcopy(self.nlsubs_raw1)
    list_tmp3 = deepcopy(self.allsubs_raw1)
    # Replace substitutions inside substitutions, for both time-subscripted and steady state vars!
    mreg = re.compile('@DISCOUNT|@(E\(t.*?\)\|){0,1}.*?\(t.*?\)|@(E\(t.*?\)\|){0,1}.*?_bar')
    variables = [x[0] for x in list_tmp2] # do this once
    self.subs_vars = deepcopy(variables)
    for i,x in enumerate(list_tmp2):
        rhs_eq = list_tmp2[i][1]
        while mreg.search(rhs_eq):
            ma = mreg.search(rhs_eq)
            pos, poe = ma.span()
            indx = variables.index(ma.group())
            # Important: When substituting in, put the term between brackets!
            rhs_eq = rhs_eq[:pos]+'('+list_tmp2[indx][1]+')'+rhs_eq[poe:]
        # Don't do below anymore as the term above has been inserted between brackets, so okay that way
        '''
        # Finally get rid of possible `+-` or `-+` occurences
        while '+-' in rhs_eq or '-+' in rhs_eq or '++' in rhs_eq:
            rhs_eq = rhs_eq.replace('+-','-')
            rhs_eq = rhs_eq.replace('-+','-')
            rhs_eq = rhs_eq.replace('++','+')
        '''
        list_tmp2[i][1] = rhs_eq
    self.nlsubs_raw2 = deepcopy(list_tmp2)
    return self

def ff_chron_str(self,str1='',ff_int=1,vtype='all'):
    '''
    This forwards all variables in an algebraic string expression by ff_int,
    but it leaves the timing of the expectations operator untouched.
    '''
    _mregv1b = '(?<!E)\(t(?P<oper>[\+|-]{0,1})(?P<counto>\d{0,2})\)'
    _mregv1c = '(?<=E)\(t(?P<oper>[\+|-]{0,1})(?P<counto>\d{0,2})\)(?=\|)'
    mregv1b = re.compile(_mregv1b)
    mregv1c = re.compile(_mregv1c)
    patup = ('{-10,10}|None','endo|con|exo|iid|other','{-10,10}')
    reg_li = self.vreg(patup,str1,True,'max')
    if type(reg_li) == type(False):
        print "ERROR at: ",str1
        sys.exit()    
    var_li = list(reg_li)
    var_li.reverse()
    for varo in var_li:
        if vtype != 'all' and varo[1][0] != vtype:
            continue
        elif vtype != 'all' and varo[1][0] != vtype:
            continue
        elif vtype != 'all' and varo[1][0] != vtype:
            continue
        elif vtype != 'all' and varo[1][0] != vtype:
            continue
        varn = varo[0]
        ma = mregv1b.search(varn)
        starts = ma.start()
        ends = ma.end()
        matot = ma.group()
        oper = ma.group('oper')
        counto = ma.group('counto')
        varpos = varo[3]
        if oper == '':
            oper = '+'
            counto = int(ff_int)
        elif oper == '+':
            counto = int(counto)+ff_int
            counto = str(counto)
        elif oper == '-':
            counto = -int(counto)+ff_int
            counto = str(counto)
            if counto == '0':
                oper = ''
                counto = ''
            elif counto[0] == '-':
                oper == '-'
                counto = counto[1]
            else:
                oper = '+'
                counto = str(counto)
        # Split off expectations operator if present
        if '|' in varn:
            expos = varn.split('|')[0]
            rems = varn.split('|')[1]
        else:
            expos = ''
            rems = varn
        if expos == '':
            varn_new = rems.split('(')[0].replace('-','').replace('+','')+'(t'+str(oper)+str(counto)+')'
        else:
            varn_new = expos+'|'+rems.split('(')[0].replace('-','').replace('+','')+'(t'+str(oper)+str(counto)+')'
        # Add an expectations term if needed, but only if it is not already inside the original variable
        if oper == '+' and int(counto) > 0:
            if not mregv1c.search(varn_new): varn_new = 'E(t)|'+varn_new
        str1 = str1[:varpos[0]]+varn_new+str1[varpos[1]:]
    return str1

def bb_chron_str(self,str1='',bb_int=1,vtype='all'):
    '''
    This backwards (lags) all variables in an algebraic string expression by bb_int,
    but it leaves the timing of the expectations operator untouched.
    '''
    _mregv1b = '(?<!E)\(t(?P<oper>[\+|-]{0,1})(?P<counto>\d{0,2})\)'
    mregv1b = re.compile(_mregv1b)    
    patup = ('{-10,10}|None','endo|con|exo|iid|other','{-10,10}')
    var_li = list(self.vreg(patup,str1,True,'max'))
    var_li.reverse()
    for varo in var_li:
        if vtype != 'all' and varo[1][0] != vtype:
            continue
        elif vtype != 'all' and varo[1][0] != vtype:
            continue
        elif vtype != 'all' and varo[1][0] != vtype:
            continue
        elif vtype != 'all' and varo[1][0] != vtype:
            continue
        varn = varo[0]
        ma = mregv1b.search(varn)
        starts = ma.start()
        ends = ma.end()
        matot = ma.group()
        oper = ma.group('oper')
        counto = ma.group('counto')
        varpos = varo[3]
        if oper == '':
            oper = '-'
            counto = int(bb_int)
        elif oper == '+':
            counto = int(counto)-bb_int
            counto = str(counto)
            if counto == '0':
                oper = ''
                counto = ''
            elif counto[0] == '-':
                oper == '-'
                counto = counto[1]
            else:
                oper = '+'
                counto = str(counto)
        elif oper == '-':
            counto = -int(counto)-bb_int
            counto = str(counto)[1]
        if 'E(t)|' not in varn:
            varn_new = varn.split('(')[0].replace('-','').replace('+','')+'(t'+str(oper)+str(counto)+')'
        elif 'E(t)|' in varn and counto == '':
            varn_new = varn.split('E(t)|')[1].split('(')[0].replace('-','').replace('+','')+'(t'+str(oper)+str(counto)+')'            
        elif 'E(t)|' in varn and int(counto) > 0:
            varn_new = 'E(t)|'+varn.split('E(t)|')[1].split('(')[0].replace('-','').replace('+','')+'(t'+str(oper)+str(counto)+')'
        elif 'E(t)|' in varn and int(counto) <= 0:
            varn_new = varn.split('E(t)|')[1].split('(')[0].replace('-','').replace('+','')+'(t'+str(oper)+str(counto)+')'
        # Compare this line with ff_chron_str, here I do not add any expectations term
        str1 = str1[:varpos[0]]+varn_new+str1[varpos[1]:]
    return str1

def ss_chron_str(self,str1=''):
    '''
    This turns all variables in an algebraic string expression into steady state equivalents.
    '''
    patup = ('{-10,10}|None','endo|con|exo|other','{-10,10}')
    try:
        var_li = list(self.vreg(patup,str1,True,'max'))
    except:
        print "Model parsing error, problem with processing this text string:\n"+"'"+str1+"'."
        sys.exit()

    var_li.reverse()
    for varo in var_li:
        varn = varo[0]
        varpos = varo[3]
        if '|' in varn:
            varn_new = varn.split('|')[1].split('(')[0]+'_bar'
        else:
            varn_new = varn.split('(')[0]+'_bar'
        str1 = str1[:varpos[0]]+varn_new+str1[varpos[1]:]
    return str1

def chg_vtimings(self,eqli,vdico):
    vtiming = self._vtiming
    for keyo in vdico.keys():
        if vdico[keyo] != vtiming[keyo]:
            diffli = list(np.array(vdico[keyo]) - np.array(vtiming[keyo]))
            if diffli[0] < 0:
                for i1,lino in enumerate(eqli):
                    if keyo == 'exo':
                        eqli[i1] = bb_chron_str(self,str1=eqli[i1],bb_int=abs(diffli[0]),vtype=keyo)
                        eqli[i1] = bb_chron_str(self,str1=eqli[i1],bb_int=abs(diffli[0]),vtype='iid')
                    else:
                        eqli[i1] = bb_chron_str(self,str1=eqli[i1],bb_int=abs(diffli[0]),vtype=keyo)
            elif diffli[0] > 0:
                for i1,lino in enumerate(eqli):
                    if keyo == 'exo':
                        eqli[i1] = ff_chron_str(self,str1=eqli[i1],ff_int=abs(diffli[0]),vtype=keyo)
                        eqli[i1] = ff_chron_str(self,str1=eqli[i1],ff_int=abs(diffli[0]),vtype='iid')
                    else:
                        eqli[i1] = ff_chron_str(self,str1=eqli[i1],ff_int=abs(diffli[0]),vtype=keyo)
    return eqli

def mk_steady(self):
    list_tmp2 = deepcopy(self.nlsubs_raw2)
    _mreg = 'SS\{.*?\}'
    mreg = re.compile(_mreg)
    for i1,elem in enumerate(list_tmp2):
        # If there is an unreplaced DIFF inside the SS, then skip for now...
        if list_tmp2[i1][1][:2] == 'SS' and 'DIFF' in list_tmp2[i1][1][2:] : continue
        while mreg.search(list_tmp2[i1][1]):
            ma = mreg.search(list_tmp2[i1][1])
            matn = ma.group()
            starts = ma.start()
            ends = ma.end()
            str_tmp = matn
            str_tmp = str_tmp.split('{')[1].split('}')[0]
            str_tmp = ss_chron_str(self,str1=str_tmp)
            list_tmp2[i1][1] = list_tmp2[i1][1][:starts]+str_tmp+list_tmp2[i1][1][ends:]
    self.nlsubs_raw2 = deepcopy(list_tmp2)  
    return self

def mk_steady2(self):
    list_tmp2 = deepcopy(self.foceqs2)
    patup = ('{-10,10}|None','endo|con|exo|other','{-10,10}')
    vreg = self.vreg
    for i1,elem in enumerate(list_tmp2):
        varli = list(vreg(patup,list_tmp2[i1],True,'max'))
        varli.reverse()
        for varo in varli:
            vpos = varo[3]
            list_tmp2[i1] = list_tmp2[i1][:vpos[0]]+varo[2][1]+'_bar'+list_tmp2[i1][vpos[1]:]
    self.foceqss = deepcopy(list_tmp2)  
    return self

def mk_timeshift(self):
    list_tmp2 = deepcopy(self.nlsubs_raw2)
    _mreg = '(?<=\*)FF[_](?P<fint>\d{1,2})\{.*?\}'
    _mreg2 = '(?<=\*)BB[_](?P<bint>\d{1,2})\{.*?\}'
    _mreg_b = '(?<!\*)FF[_](?P<fint>\d{1,2})\{.*?\}'
    _mreg2_b = '(?<!\*)BB[_](?P<bint>\d{1,2})\{.*?\}'
    _mreg3 = '\s*DIFF{.*?,.*?}\s*'
    mreg = re.compile(_mreg)
    mreg2 = re.compile(_mreg2)
    mregb= re.compile(_mreg_b)
    mreg2b = re.compile(_mreg2_b)
    mreg3 = re.compile(_mreg3)
    for i1,elem in enumerate(list_tmp2):
        # First search for forward shifting terms
        while mreg.search(list_tmp2[i1][1]):
            ma = mreg.search(list_tmp2[i1][1])
            matn = ma.group()
            # Skip if the is a part which needs to be differentiated
            if mreg3.search(matn): break            
            starts = ma.start()
            ends = ma.end()
            fint = int(ma.group('fint'))
            str_tmp = matn
            str_tmp = str_tmp.split('{')[1].split('}')[0]
            str_tmp = ff_chron_str(self,str1=str_tmp,ff_int=fint)
            list_tmp2[i1][1] = list_tmp2[i1][1][:starts]+str_tmp+list_tmp2[i1][1][ends:]
        # First search for forward shifting terms
        while mregb.search(list_tmp2[i1][1]):
            ma = mregb.search(list_tmp2[i1][1])
            matn = ma.group()
            # Skip if the is a part which needs to be differentiated
            if mreg3.search(matn): break            
            starts = ma.start()
            ends = ma.end()
            fint = int(ma.group('fint'))
            str_tmp = matn
            str_tmp = str_tmp.split('{')[1].split('}')[0]
            str_tmp = ff_chron_str(self,str1=str_tmp,ff_int=fint)
            list_tmp2[i1][1] = list_tmp2[i1][1][:starts]+str_tmp+list_tmp2[i1][1][ends:]
        # Now search for backward shifting terms
        while mreg2.search(list_tmp2[i1][1]):
            ma = mreg2.search(list_tmp2[i1][1])
            matn = ma.group()
            # Skip if the is a part which needs to be differentiated
            if mreg3.search(matn): break  
            starts = ma.start()
            ends = ma.end()
            bint = int(ma.group('bint'))
            str_tmp = matn
            str_tmp = str_tmp.split('{')[1].split('}')[0]
            str_tmp = bb_chron_str(self,str1=str_tmp,bb_int=bint)
            list_tmp2[i1][1] = list_tmp2[i1][1][:starts]+str_tmp+list_tmp2[i1][1][ends:]
        # Now search for backward shifting terms
        while mreg2b.search(list_tmp2[i1][1]):
            ma = mreg2b.search(list_tmp2[i1][1])
            matn = ma.group()
            # Skip if the is a part which needs to be differentiated
            if mreg3.search(matn): break  
            starts = ma.start()
            ends = ma.end()
            bint = int(ma.group('bint'))
            str_tmp = matn
            str_tmp = str_tmp.split('{')[1].split('}')[0]
            str_tmp = bb_chron_str(self,str1=str_tmp,bb_int=bint)
            list_tmp2[i1][1] = list_tmp2[i1][1][:starts]+str_tmp+list_tmp2[i1][1][ends:]
    self.nlsubs_raw2 = deepcopy(list_tmp2)  
    return self

def ext_differ_out(self):
    '''
    This function will check differentiation instructions and augment the original one
    for timeshifts and the discount factor
    '''
    list_tmp2 = deepcopy(self.nlsubs_raw2)
    # Also allow for differentiation in substitution list
    _mreg = '\s*DIFF{.*?,.*?}\s*'
    mreg = re.compile(_mreg)
    _mregv1 = '\w+\d*_bar'
    patup = ('{-10,10}|None','endo|con|exo|other','{-10,10}')
    for kk1,elem in enumerate(list_tmp2):
        # Skip any line in which the steady state needs to be take before DIFF
        if list_tmp2[kk1][1][:4] == 'DIFF' and 'SS{' in list_tmp2[kk1][1]: continue
        # Also skip cases such as @r_bar = DIFF{z_bar*k_bar**(rho)*l_bar**(1-rho),k_bar}
        if list_tmp2[kk1][1][:4] == 'DIFF' and not self.vreg(patup,list_tmp2[kk1][1],True,'max') and\
           "_bar" in list_tmp2[kk1][1].split(',')[1]: continue        
        if mreg.search(list_tmp2[kk1][1]):
            maoutli = mreg.finditer(list_tmp2[kk1][1])
            maoutli = [elem for elem in maoutli]
            maoutli.reverse()
            for maout in maoutli:
                expout = maout.group()
                starts_out = maout.start()
                ends_out = maout.end()
                evalstr = expout.replace('DIFF','')
                evalstr = evalstr.replace('{','')
                evalstr = evalstr.replace('}','')
                differo = evalstr.split(',')[1]
                evalstr = evalstr.split(',')[0]
                # When the variable differo is steady state then we can skip this test
                if '_bar' in differo: continue
                # Should be only one variable, so take the first element
                diff_li = list(self.vreg(patup,differo,True,'max'))[0]
                var_li = list(self.vreg(patup,evalstr,True,'max'))
                # Expectations timing and differos stem name
                diff_conf = diff_li[2][:2]
                # The differos time subscript
                diff_conf2 = int(diff_li[2][-1])
                # Check for case that we need to augment the expression to be differentiated
                modcase = False
                chrondiff = []
                for elem in var_li:
                    if elem[2][:2] == diff_conf and int(elem[2][-1]) != diff_conf2:
                        chrondiff.append((-1)*(diff_conf2+int(elem[2][-1])))
                        modcase = True
                if modcase:
                    if '@DISCOUNT' not in dict(self.nlsubs_raw2).keys():
                        print "ERROR: For this model you need to define the discount rate explicitly!"
                        print "You can do this by inserting the special reserved @DISCOUNT variable into the substitution section"
                        sys.exit()
                    else:
                        disco = dict(self.nlsubs_raw2)['@DISCOUNT']
                    maxfor = max(chrondiff)
                    minfor = min(chrondiff)
                    finalexp = 'DIFF{'+evalstr
                    for kk2 in range(minfor,maxfor+1):
                        if kk2 == 0: continue
                        elif kk2 > 0: finalexp += '+'+disco+'**'+'('+str(kk2)+')'+'*FF_'+str(kk2)+'{'+evalstr+'}'
                        elif kk2 < 0: finalexp += '+'+disco+'**'+'('+str(-kk2)+')'+'*BB_'+str(kk2)+'{'+evalstr+'}'
                    finalexp += ','+differo+'}'
                    list_tmp2[kk1][1] = list_tmp2[kk1][1][:starts_out]+finalexp+list_tmp2[kk1][1][ends_out+1:]
    self.nlsubs_raw2 = deepcopy(list_tmp2)
    return self
            


def differ_out(self):
    # Copy in raw nlsubs which has substitutions inside
    # substitutions already replaced by previous function call
    list_tmp2 = deepcopy(self.nlsubs_raw2)
    # Also allow for differentiation in substitution list
    _mreg = '\s*DIFF{.*?,.*?}\s*'
    mreg = re.compile(_mreg)
    _mregv1 = '\w+\d*_bar'
    _mregv1b = '(?<!E)\(t[\+|-]{0,1}\d{0,2}\)'
    mregv1b = re.compile(_mregv1b)
    _mregv1b2 = '(?<!E)__ll__t[\+|-]{0,1}\d{0,2}__rr__'
    mregv1b2 = re.compile(_mregv1b)
    _mregv1bb = '\(t[\+|-]\d{1,2}\)'    
    mregv1bb = re.compile(_mregv1bb)
    _mregv1bb2 = '__l__t[\+|-]\d{1,2}__r__'    
    mregv1bb2 = re.compile(_mregv1bb2)    
    _mregv1c = '\([p+|m+]\)'
    mregv1c = re.compile(_mregv1c)
    _mregv1d = 'E\(t[\+|-]{0,1}\d{0,2}\)\|'
    mregv1d = re.compile(_mregv1d)
    _mregv1e = 'E\[t[\+|-]{0,1}\d{0,2}]\|'
    mregv1e = re.compile(_mregv1e)
    _mreglog = 'LOG\(.*?\)'
    _mregexp = 'EXP\(.*?\)'
    mregle_ng = re.compile(_mregexp+'|'+_mreglog)
    _mreglog2 = 'LOG\[.*?]'
    _mregexp2 = 'EXP\[.*?]'
    mregle2_ng = re.compile(_mregexp2+'|'+_mreglog2)
    _mreglog = 'LOG\(.*\)'
    _mregexp = 'EXP\(.*\)'
    mregle_gg = re.compile(_mregexp+'|'+_mreglog)
    _mreglog2 = 'LOG\[.*]'
    _mregexp2 = 'EXP\[.*]'
    mregle2_gg = re.compile(_mregexp2+'|'+_mreglog2)
    _mregsh = '(?<!DI)FF[_]\d{1,2}|BB[_]\d{1,2}'
    mregsh = re.compile(_mregsh)
    patup = ('{-10,10}|None','endo|con|exo|other','{-10,10}')
    # Collect some necessary info for steady state substitutions
    var_bar = []
    varnames = deepcopy(self.vardic)
    for elem in ['con','endo','exo','other']:
        tmp_li = [x[0].split('(')[0]+'_bar' for x in varnames[elem]['var']]
        for elem2 in tmp_li:
            var_bar.append(elem2)
    for kk1,elem in enumerate(list_tmp2):
        # Skip any line in which
        if list_tmp2[kk1][1][:4] == 'DIFF' and 'SS{' in list_tmp2[kk1][1]: continue
        while mreg.search(list_tmp2[kk1][1]):
            maout = mreg.search(list_tmp2[kk1][1])
            expout = maout.group()
            starts_out = maout.end()
            ends_out = maout.start()
            evalstr = expout.replace('DIFF','')
            evalstr = evalstr.replace('{','')
            evalstr = evalstr.replace('}','')
            differo = evalstr.split(',')[1]
            # Skip if differo still has uncomputed timeshifter
            if mregsh.search(differo): break
            # Also skip if evalstr has uncomputed timeshifter
            if mregsh.search(evalstr): break
            evalstr = evalstr.split(',')[0]
            time_vars = False
            var_li = self.vreg(patup,evalstr,True,'max')
            if var_li: time_vars = True
            #########################################################
            # Do for steady state expressions, as is very easy, CASE1
            #########################################################
            if '_bar' in evalstr and not time_vars and '_bar' in differo:
                # Now substitute out exp and log in terms of sympycore expressions
                elog = re.compile('LOG\(')
                while elog.search(evalstr):
                    ma = elog.search(evalstr)
                    pos = ma.span()[0]
                    poe = ma.span()[1]
                    evalstr = evalstr[:pos]+'SP.log('+evalstr[poe:]
                eexp = re.compile('EXP\(')
                while eexp.search(evalstr):
                    ma = eexp.search(evalstr)
                    pos = ma.span()[0]
                    poe = ma.span()[1]
                    evalstr = evalstr[:pos]+'SP.exp('+evalstr[poe:]
                # Now populate scope with sympy symbols
                tmp_dic={}
                for elem in var_bar:
                    tmp_dic[elem] = SP.Symbol(elem)
                locals().update(tmp_dic)
                tmp_dic = {}
                for elem in self.paramdic.keys():
                    tmp_dic[elem] = SP.Symbol(elem)
                locals().update(tmp_dic)
                # Also expose any variables from the ssidic, just in case
                tmp_dic = {}
                for elem in self.ssidic.keys():
                    tmp_dic[elem] = SP.Symbol(elem)
                locals().update(tmp_dic)
                # Also expose the differo variable
                locals()[differo] = SP.Symbol(differo)
                # Population of scope done, now do calculation and continue in loop
                expr_bar = eval(evalstr)
                resstr = expr_bar.diff(locals()[str(differo)])
                list_tmp2[kk1][1] = str(resstr)
                continue
            ##############################################################################
            # Do for steady state expressions, as is very easy, CASE2, needs working varli
            ##############################################################################
            
            ############## Generate varli only here, as it was not needed above (it was, but only for testing) ############### 
            try:
                var_li = list(self.vreg(patup,evalstr,True,'max'))
                if var_li: time_vars = True
            except:
                print "Model parsing error, problem with processing this text string:\n"+"'"+list_tmp2[kk1][0]+" = "+list_tmp2[kk1][1]+"'."
                sys.exit()
            ###################################################################################################################

            if '_bar' not in evalstr and not time_vars and '_bar' in differo:
                # First replace all chronological variables in evalstr with _bar equivalents
                varbar_li = deepcopy(var_li)
                varbar_li.reverse()
                for varo in varbar_li:
                    vpos = varo[3]
                    evalstr = evalstr[:vpos[0]]+varo[2][1]+'_bar'+evalstr[vpos[1]:]
                # Now substitute out exp and log in terms of sympycore expressions
                elog = re.compile('LOG\(')
                while elog.search(evalstr):
                    ma = elog.search(evalstr)
                    pos = ma.span()[0]
                    poe = ma.span()[1]
                    evalstr = evalstr[:pos]+'SP.log('+evalstr[poe:]
                eexp = re.compile('EXP\(')
                while eexp.search(evalstr):
                    ma = eexp.search(evalstr)
                    pos = ma.span()[0]
                    poe = ma.span()[1]
                    evalstr = evalstr[:pos]+'SP.exp('+evalstr[poe:]
                # Now populate scope with sympy symbols
                tmp_dic={}
                for elem in var_bar:
                    tmp_dic[elem] = SP.Symbol(elem)
                locals().update(tmp_dic)
                tmp_dic = {}
                for elem in self.paramdic.keys():
                    tmp_dic[elem] = SP.Symbol(elem)
                locals().update(tmp_dic)
                # Also expose any variables from the ssidic, just in case
                tmp_dic = {}
                for elem in self.ssidic.keys():
                    tmp_dic[elem] = SP.Symbol(elem)
                locals().update(tmp_dic)
                # Also expose the differo variable
                locals()[differo] = SP.Symbol(differo)
                # Population of scope done, now do calculation and continue in loop
                expr_bar = eval(evalstr)
                resstr = expr_bar.diff(locals()[str(differo)])
                list_tmp2[kk1][1] = str(resstr)
                continue
            ###################################################
            # Steady State branch ends here
            ###################################################
            var_li2 = deepcopy(var_li)
            var_li2.reverse()
            ss_li = [x[2][1]+'_bar' for x in var_li2]
            # Replace t+1 or t-1 with something without the operators, in evalstr
            for jj1,elem in enumerate(var_li2):
                tmp_li = list(elem)
                # Replace expectations operators with something else inside evalstr
                if mregv1d.search(tmp_li[0]):
                    ma = mregv1d.search(tmp_li[0])
                    vname = ma.group()
                    ends = ma.end()
                    starts = ma.start()
                    vname = vname.replace('(','__ll__')
                    vname = vname.replace(')','__rr__')
                    vname = vname.replace('|','DELIM__')
                    tmp_li[0] = tmp_li[0][:starts]+vname+tmp_li[0][ends:]                      
                evalstr = evalstr[:elem[3][0]]+tmp_li[0].\
                replace('(','__l__').\
                replace(')','__r__').\
                replace('|','DELIM__')+\
                evalstr[elem[3][1]:]

            # Replace expectations operators with something else inside varli
            for i1,varo in enumerate(var_li):
                if mregv1d.search(varo[0]):
                    str1 = varo[0].split('|')[1]
                    str2 = varo[0].split('|')[0]
                    str2 = str2.replace('(','__ll__')
                    str2 = str2.replace(')','__rr__')
                    var_li[i1] = list(varo)
                    var_li[i1][0] = str2+'DELIM__'+str1
            # Replace the LOGs and EXPs with square brackets
            while mregle_ng.search(evalstr):
                ma = mregle_ng.search(evalstr)
                starts = ma.start()
                ends = ma.end()
                evalstr = evalstr[:ends-1] + ']' + evalstr[ends:]
                evalstr = evalstr[:starts+3] + '[' + evalstr[starts+4:]
            # Replace t+1 or t-1 with something without the operators, inside var_li
            for i1,varo in enumerate(var_li):
                var_li[i1] = list(varo)
                ma = mregv1bb.search(varo[0])
                if ma:
                    ends = ma.end()
                    starts = ma.start()
                    if '+' in varo[0]:
                        str1 = varo[0].split('(')[0]
                        counto = varo[0].split('+')[1][0]
                        var_li[i1][0] = str1+'__l__'+int(counto)*'p' + '__r__'
                    if '-' in varo[0]:
                        str1 = varo[0].split('(')[0]
                        counto = varo[0].split('-')[1][0]
                        var_li[i1][0] = str1+'__l__'+int(counto)*'m' + '__r__'
            while mregv1bb2.search(evalstr):
                ma = mregv1bb2.search(evalstr)
                varn = ma.group()
                ends = ma.end()
                starts = ma.start()
                if '+' in varn:
                    str1 = varn.split('__l__')[0]
                    counto = varn.split('+')[1][0]
                    varn_new = str1+'__l__'+int(counto)*'p' + '__r__'
                    evalstr = evalstr[:starts]+varn_new+evalstr[ends:]
                if '-' in varn:
                    str1 = varn.split('__l__')[0]
                    counto = varn.split('-')[1][0]
                    varn_new = str1+'__l__'+int(counto)*'m' + '__r__'
                    evalstr = evalstr[:starts]+varn_new+evalstr[ends:]
            # Replace left and right round brackets for variables and expose to sympycore
            for i1,varo in enumerate(var_li):
                str_tmp2 = var_li[i1][0]
                str_tmp2 = str_tmp2.replace('(','__l__')
                str_tmp2 = str_tmp2.replace(')','__r__')
                locals()[str_tmp2] = SP.Symbol(str_tmp2)
            for varo in self.paramdic.keys(): locals()[varo] = SP.Symbol(varo)
            # Replace left and right round brackets for the differo variable and expose to sympycore
            str_tmp3 = deepcopy(differo)
            # First, also check for (t+x),(t-x) or (t) in differo and replace with something readable by sympycore
            while mregv1b.search(str_tmp3):
                ma = mregv1b.search(str_tmp3)
                ends = ma.end()
                starts = ma.start()
                if '+' in str_tmp3:
                    counto = str_tmp3.split('+')[-1][0]
                    post = str_tmp3[starts:]
                    pre = str_tmp3[:starts]
                    # Also replace brackets
                    if ')' in pre: pre = pre.replace(')','__rr__')
                    if '(' in pre: pre = pre.replace('(','__ll__')
                    if ')' in post: post = post.replace(')','__r__')
                    if '(' in post: post = post.replace('(','__l__')                    
                    str_tmp3 = pre+'__l__'+int(counto)*'p' + '__r__' 
                elif '-' in str_tmp3:
                    counto = str_tmp3.split('-')[-1][0]
                    post = str_tmp3[starts:]
                    pre = str_tmp3[:starts]
                    # Also replace brackets
                    if ')' in pre: pre = pre.replace(')','__rr__')
                    if '(' in pre: pre = pre.replace('(','__ll__')
                    if ')' in post: post = post.replace(')','__r__')
                    if '(' in post: post = post.replace('(','__l__')                    
                    str_tmp3 = pre+'__l__'+int(counto)*'m' + '__r__'
                else:
                    post = str_tmp3[starts:]
                    pre = str_tmp3[:starts]
                    # Also replace brackets
                    if ')' in pre: pre = pre.replace(')','__rr__')
                    if '(' in pre: pre = pre.replace('(','__ll__')
                    if ')' in post: post = post.replace(')','__r__')
                    if '(' in post: post = post.replace('(','__l__')                    
                    str_tmp3 = pre+'__l__'+'t' + '__r__'                    
            differo_new = deepcopy(str_tmp3)
            # Also replace the delimiter when expectations are present in differo
            while '|' in differo_new: differo_new = differo_new.replace('|','DELIM__')
            locals()[differo_new] = SP.Symbol(differo_new)
            # Replace left and right brackets for the entire expression before calling diff
            var_li.reverse()
            for varo in var_li:
                varn_orig = varo[0]
                varn = varo[0].replace(')','__r__')
                varn = varn.replace('(','__l__')
                evalstr = evalstr.replace(varn_orig, varn)
            # Replace the LOGs and EXPs with round brackets again
            while mregle2_ng.search(evalstr):
                ma = mregle2_ng.search(evalstr)
                starts = ma.start()
                ends = ma.end()
                evalstr = evalstr[:ends-1] + ')' + evalstr[ends:]
                evalstr = evalstr[:starts+3] + '(' + evalstr[starts+4:]
            # Now substitute out exp and log in terms of sympycore expressions
            elog = re.compile('LOG\(')
            while elog.search(evalstr):
                ma = elog.search(evalstr)
                pos = ma.span()[0]
                poe = ma.span()[1]
                evalstr = evalstr[:pos]+'SP.log('+evalstr[poe:]
            eexp = re.compile('EXP\(')
            while eexp.search(evalstr):
                ma = eexp.search(evalstr)
                pos = ma.span()[0]
                poe = ma.span()[1]
                evalstr = evalstr[:pos]+'SP.exp('+evalstr[poe:]
            # Now evaluate and differentiate
            # Before evaluating expose the self.paramdic and self.ssidic to locals
            tmp_dic = {}
            for elem in self.paramdic.keys():
                tmp_dic[elem] = SP.Symbol(elem)
            locals().update(tmp_dic)
            # Also expose any variables from the ssidic, just in case
            if 'ssidic' in dir(self):
                tmp_dic = {}
                for elem in self.ssidic.keys():
                    tmp_dic[elem] = SP.Symbol(elem)
                locals().update(tmp_dic)
            # Also expose any variables from the ss_li, just in case
            tmp_dic = {}
            for elem in ss_li:
                tmp_dic[elem] = SP.Symbol(elem)
            locals().update(tmp_dic)
            expr = eval(evalstr)
            try:
                expr = eval(evalstr)
            except:
                print "Parse ERROR: Could not evaluate/differentiate expression: "
                print list_tmp2[kk1][0]+" = "+list_tmp2[kk1][1]
                sys.exit()
            resstr = expr.diff(locals()[str(differo_new)])
            resstr = str(resstr)
            # Now switch back to normal notation with brackets
            while '__l__' in resstr:
                resstr = resstr.replace('__l__','(')
            while '__r__' in resstr:
                resstr = resstr.replace('__r__',')')
            while '__ll__' in resstr:
                resstr = resstr.replace('__ll__','(')
            while '__rr__' in resstr:
                resstr = resstr.replace('__rr__',')')
            # Also replace the DELIM with |
            while 'DELIM__' in resstr: resstr = resstr.replace('DELIM__','|')
            # Now also switch back to normal t+1/t-x notation
            while mregv1c.search(resstr):
                ma = mregv1c.search(resstr)
                ends = ma.end()
                starts = ma.start()
                str3 = ma.group()
                lengo = len(str3[1:-1])
                if 'p' in str3: resstr = resstr[:starts]+'(t+'+str(lengo)+')'+resstr[ends:]
                elif 'm' in str3: resstr = resstr[:starts]+'(t-'+str(lengo)+')'+resstr[ends:]
            # Replace with the differentiate term, but also take brackets around it just in case    
            list_tmp2[kk1][1] = list_tmp2[kk1][1].replace(expout,'('+resstr+')')
    self.nlsubs_raw2 = deepcopy(list_tmp2)
    self.nlsubs = deepcopy(dict(list_tmp2))
    self.nlsubs_list = deepcopy(list_tmp2)
    return self

def premknonlinsys(self,secs):
    '''
    This takes the raw lines of the FOCs and does some joining, splitting and stripping
    '''
    # Make the non-linear system by joining lines and stripping
    list_tmp1 = []
    i1 = 0
    linecounter = 0
    for x in secs['focs'][0]:
        if x.endswith(('...','\\')):
            linecounter += 1
        else:
            if linecounter == 0:
                if ']' in x: line = x.replace(';','').split(']')[1].strip()
                else: line = x.replace(';','').strip()
                line = line.split('=')[0].strip()
                list_tmp1.append(line)
            elif linecounter > 0:
                str_tmp = ''
                for y in secs['focs'][0][i1-linecounter:i1+1]:
                    if ']' in y: str_tmp += y.split(']')[1].replace('...','').replace('\\','').replace(';','').strip()
                    else: str_tmp += y.replace('...','').replace('\\','').replace(';','').strip()
                if ']' in x: line = str_tmp.split(']')[1].strip()
                else: line = str_tmp.strip()
                linecounter = 0 
                line = line.split('=')[0].strip()
                list_tmp1.append(line)
        i1 += 1
    self.foceqs = deepcopy(list_tmp1)
    return self

def premknonlinsys2(self, secs):
    list_tmp1 = deepcopy(self.foceqs)
    variables = deepcopy(self.subs_vars)
    subs_found = []
    i1 = 0    
    for x in list_tmp1:
        # substitute out in main nonlinear equation system
        list_tmp2 = deepcopy(self.nlsubs_list)
        mreg = re.compile('@(E\(t.*?\)\|){0,1}.*?\(t.*?\)')
        for i,x in enumerate(list_tmp1):
            rhs_eq = list_tmp1[i]
            while mreg.search(rhs_eq):
                ma = mreg.search(rhs_eq)
                subv = ma.group()
                if subv not in subs_found: subs_found.append(subv)
                pos, poe = ma.span()
                indx = variables.index(subv)
                rhs_eq = rhs_eq[:pos]+'('+list_tmp2[indx][1]+')'+\
                    rhs_eq[poe:]
            list_tmp1[i] = rhs_eq
        i1+=1
    self.foceqs2 = deepcopy(list_tmp1)
    self.subs_found = deepcopy(subs_found)
    
    # Remove the elements from nlsubs_list which were not found in the nlsys_list!
    # This is important because pymaclab also generates equations (and auxiliary variables)
    # for the expressions declared in the nonlinear substitution system
    self.nlsubs_list = [x for x in self.nlsubs_list if x[0] in self.subs_found]
    for i1,elem in enumerate(self.vardic['other']['var']):
        if '@'+elem[0] not in self.subs_found:
            self.vardic['other']['var'].pop(i1)
            self.vardic['other']['mod'].pop(i1)

    return self

def mknonlinsys(self, secs):
    """
    Create Non-Linear FOC System
    """
    # Here we introduce time-shifted auxiliary variables into the system of FOCs if needed
    # and also add them to the vardic and audic, also new variables get added to bottom of nlsys_list
    # The returned list is just the new augmented nlsys_list with the auxiliary variables in the system
    list_tmp1 = deepcopy(self.foceqs2)
    self, list_tmp1 = mkaug2(self,insys=list_tmp1,othersys=None)

    if all([False if 'None' in x else True for x in secs['vsfocs'][0]]):
        ## The point of this section below this conditional test is to replace variables
        ## inside nlsubs_list with their time-shifted (auxiliary) equivalent
        ## When doing so we may need to add newly found auxiliary variables to the bottom of nlsys_list
        variables = deepcopy(self.subs_vars)
        
        # Here we do the substitutions inside the variable substitution list, outup contains two lists
        list_tmp3 = [x[1] for x in deepcopy(self.nlsubs_list)]
        self, outtup = mkaug2(self,insys=list_tmp3,othersys=list_tmp1)

        # Then the equation expressions (declarations) with substituted time elements get inserted back in
        list_tmp3 = outtup[0] # This is the system of substitutions
        list_tmp2 = deepcopy(self.nlsubs_list) # This is the old system of substitutions, needs updating
        list_tmp1 = outtup[1] # This is the FOC system
        for i1,x in enumerate(list_tmp3):
            list_tmp2[i1][1] = list_tmp3[i1]


        # Below all other objects get updated in order to take information into account
        # which was computed in the above
        self.nlsubs = dict(list_tmp2)
        nlsubs2 = {}
        for x in [x[0] for x in self.vardic['other']['var']]:
            nlsubs2[x] = self.nlsubs['@'+x]
        self.nlsubs2 = nlsubs2

        # Create ordered nlsubsys
        if self.vardic['other']['var']:
            nlsubsys = []
            varother = self.vardic['other']['var']
            for vari in [x[0] for x in varother]:
                nlsubsys.append(nlsubs2[vari])
            self.nlsubsys = nlsubsys

    # Count the number of distinct forward expectations
    # AND the no of equations that contain them
    ffli = []
    count = 0
    patup = ('0','endo|con|exo','{1,10}')
    for line in list_tmp1[:-self.nexo]:
        outli = self.vreg(patup,line,True,'min')
        if outli:
            count = count + 1
            for elem in [x[0] for x in outli]:
                if elem not in ffli:
                    ffli.append(elem)
    self.ffen = count
    self.ffli = ffli
    self.fflin = len(ffli)

    # Now create simplified vdic with possibly new augmented vars
    vdic = dict([[x,self.vardic[x]['var']] for x in self.vardic.keys()])
    self.vdic = vdic

    # Finally, recomputed nendo, ncon, etc.
    self.nendo = len(self.vardic['endo']['var'])
    self.nexo = len(self.vardic['exo']['var'])
    self.ncon = len(self.vardic['con']['var'])
    self.nother = len(self.vardic['other']['var'])
    self.nstat = self.nendo+self.nexo
    self.nall = self.nstat+self.ncon

    self.nlsys_list = deepcopy(list_tmp1)
    return self

def mkloglinsys2(self, inlist):
    """
    This function simply takes the left-hand side
    of each equation and takes it over to the
    right-hand side with a minus sign in front.
    Now we have equations of the form g(x)=0.
    Also takes care of fact that the term may
    already be negative. Also takes into account
    that some equations have already been written
    as g(x)=0!
    """
    _revar='(E\(t-{0,1}\+{0,1}\d*\)\|){0,1}[a-z]*(\(t-{0,1}\+{0,1}\d*\)){1,1}'
    re_var = re.compile(_revar)
    list_tmp1 = deepcopy(inlist)
    str_tmp2 = ''
    i1 = 0
    while i1 < len(list_tmp1):

        if list_tmp1[i1].split('=')[0].strip().strip(';') == '0':
            list_tmp1[i1] = list_tmp1[i1].split('=')[1].strip().strip(';')
            i1 = i1 + 1
            continue
        elif list_tmp1[i1].split('=')[1].strip().strip(';') == '0':
            list_tmp1[i1] = list_tmp1[i1].split('=')[0].strip().strip(';')
            i1 = i1 + 1
            continue

        list_tmp1[i1] = list_tmp1[i1].strip(';')[:]
        str_tmp2 = list_tmp1[i1].split('=')[0].strip()
        list_tmp1[i1] = list_tmp1[i1].split('=')[1].strip()

        while re_var.search(str_tmp2):
            ma1 = re_var.search(str_tmp2)
            pos1 = ma1.span()[0]
            poe1 = ma1.span()[1]
            # for coeff*var and coeff not begins with '-', but '+'
            if pos1 > 1 and str_tmp2[0] != '-' and str_tmp2[0] == '+':
                coeff = '-'+str_tmp2[1:pos1]
                vari = ma1.group(0)
                str_tmp2=str_tmp2[poe1:]
                if str_tmp2 == '':
                    str_tmp2 = '@'
            # for coeff*var and coeff not begins with '+', but '-'      
            elif pos1 > 1 and str_tmp2[0] != '+' and str_tmp2[0] == '-':
                coeff = '+'+str_tmp2[1:pos1]
                vari = ma1.group(0)
                str_tmp2=str_tmp2[poe1:]
                if str_tmp2 == '':
                    str_tmp2 = '@'
            # for coeff*var and coeff not begins with '+' and not begins with '-'
            elif pos1 > 1 and str_tmp2[0] != '+' and str_tmp2[0] != '-':
                coeff = '-'+str_tmp2[:pos1]
                vari = ma1.group(0)
                str_tmp2=str_tmp2[poe1:]
                if str_tmp2 == '':
                    str_tmp2 = '@'
            # for coeff == '-'
            elif pos1 == 1 and str_tmp2[0] == '-':
                coeff = '+'
                vari = ma1.group(0)
                str_tmp2=str_tmp2[poe1:]
            # for coeff == '+'
            elif pos1 == 1 and str_tmp2[0] == '+':
                coeff = '-'
                vari = ma1.group(0)
                str_tmp2=str_tmp2[poe1:]
            # for var*coeff
            elif pos1 == 0 and len(re_var.findall(str_tmp2)) > 1\
                 and str_tmp2[poe1] != '-' and str_tmp2[poe1] != '+':
                ma2 = re_var.search(str_tmp2[poe1:])
                pos2 = ma2.span()[0]+poe1
                coeff = '-'+str_tmp2[poe1:pos2]
                vari = ma1.group(0)
                str_tmp2=str_tmp2[pos2:]
            # for last bit
            elif pos1 == 0 and len(re_var.findall(str_tmp2)) == 1:
                coeff = '-'+str_tmp2[1:][poe1-1:]
                vari = ma1.group(0)
                str_tmp2=''
            # for coeff == ''
            elif pos1 == 0 and len(re_var.findall(str_tmp2)) > 1 and str_tmp2[poe1] == '-':
                coeff = '-'
                vari = ma1.group(0)
                str_tmp2=str_tmp2[poe1:]
            # for coeff == ''
            elif pos1 == 0 and len(re_var.findall(str_tmp2)) > 1 and str_tmp2[poe1] == '+':
                coeff = '-'
                vari = ma1.group(0)
                str_tmp2=str_tmp2[poe1:]
            # for last bit
            elif pos1 == 0 and len(re_var.findall(str_tmp2)) == 1:
                coeff = '-'
                vari = ma1.group(0)
                str_tmp2=''

            if coeff[-1] != '*' and coeff != '-':
                coeff = coeff+'*'
            list_tmp1[i1] = list_tmp1[i1]+coeff+vari
        str_tmp2 = ''   
        i1 = i1 + 1
    self.nlsys_list = deepcopy(list_tmp1)
    return list_tmp1

def subs_in_loglinsys(self):
    list_tmp1 = deepcopy(self.llsys_list)
    subsdic = deepcopy(self.nlsubs)
    for i1,eqo in enumerate(list_tmp1):
        while "@" in list_tmp1[i1]:
            for keyo in subsdic.keys():
                if keyo in list_tmp1[i1]: list_tmp1[i1] = list_tmp1[i1].replace(keyo,subsdic[keyo])
    return list_tmp1

# Creates the log-linear system
def mkloglinsys1(secs):
    list_tmp = []
    i1=0
    counter=0
    for x in secs['modeq'][0]:
        if '...' in x:
            counter = counter + 1
        elif '...' not in x:
            if counter == 0:
                list_tmp.append(x.replace(';','').split(']')[1].strip())
            elif counter > 0:
                str_tmp = ''
                for y in secs['modeq'][0][i1-counter:i1+1]:
                    str_tmp = str_tmp + y.replace('...','').replace(';','').strip()
                list_tmp.append(str_tmp.split(']')[1].strip())
                counter = 0 
        i1=i1+1
    return list_tmp

# Create a Variance-Covariance matrix
def mksigmat(self, secs):
    str_tmp1 = []
    str_tmp1 = secs['vcvm'][0][0].split('[')[1].rstrip()
    if str_tmp1[-2:] == '];':
        str_tmp1=str_tmp1[:-2]
    if len(secs['vcvm']) > 1:
        for x in secs['vcvm'][0][1:]:
            if x[-2:] != '];':
                str_tmp1=str_tmp1+x.lstrip().rstrip()[:]
            elif x[-2:] == '];':
                str_tmp1=str_tmp1+x.lstrip().rstrip()[:-2]
    locals().update(self.paramdic)
    locals().update(self.sstate)
    list_tmp1 = str_tmp1.split(';')
    len1 = len(list_tmp1[0].split())
    mat1=mat.zeros((len1,len1))
    i1=0
    for x in list_tmp1:
        i2=0
        # Just another trap, only to be sure...
        if ']' in x: x = x.replace(']','')
        if '[' in x: x = x.replace('[','')
        for y in x.split():
            mat1[i1,i2] = float(eval(y))
            i2=i2+1
        i1=i1+1
    return mat1 

def mkeqtype(self):
    lsys = self.llsys_list
    tup1 = ('{-1,1}|None','iid|exo','{-1,1}')
    tup2 = ('{-1,1}|None','all','{-1,1}')
    tup3 = ('{-1,1}','all','{-1,1}')
    err_indx = []
    det_indx = []
    exp_indx = []
    for x,y in zip(lsys,range(len(lsys))):
        if self.vreg(('{-1,1}','all','{-1,1}'),x,False,'max'):
            exp_indx.append(y)
        elif self.vreg((None,'exo|iid','{-1,1}'),x,False,'max'):
            if len(self.vreg((None,'exo|iid','{-1,1}'),x,True,'max'))==\
               len(self.vreg(('{-1,1}|None','all','{-1,1}'),x,True,'max')):
                err_indx.append(y)
            else:
                det_indx.append(y)
        else:
            det_indx.append(y)

    self.eqindx = {}
    self.eqindx['err'] = err_indx
    self.eqindx['det'] = det_indx
    self.eqindx['exp'] = exp_indx
    return self

# Make symbolic system and numeric as well
def mksymsys(self):
    _mreg = 'E{1,1}[^(]'
    mreg = re.compile(_mreg)
    func = []
    subli = []
    patup = ('{-10,10}|None','all','{-10,10}')
    for x in self.sstate.keys()+self.paramdic.keys():
        locals()[x] = eval("SP.Symbol('"+x+"')")
    for y in self.llsys_list:
        str_tmp = y[:]
        while 'EXP(' in str_tmp:
            str_tmp = str_tmp.replace('EXP(','SP.exp(')
        while 'LOG(' in str_tmp:
            str_tmp = str_tmp.replace('LOG(','SP.log(')
        vali = [x[0] for x in self.vreg(patup,y,True,'min')]
        vali2 = [[x,'sub'+str(u)] for x,u in zip(vali,range(0,len(vali),1))]
        vali3 = [(x[0],x[3]) for x in self.vreg(patup,str_tmp,True,'max')]
        vali3.reverse()
        valdic = dict(vali2)
        for x in vali3:
            str_tmp = str_tmp[:x[1][0]] + valdic[x[0]] + str_tmp[x[1][1]:]
        subli.append(valdic)
        for x in valdic.values():
            locals()[x] = eval("SP.Symbol('"+x+"')")
        func.append(eval(str_tmp))
    diffli = []
    i1 = 0
    for x in func:
        diffdic = {}
        for y in subli[i1].items():
            diffdic[y[0]] = eval('SP.diff(func[i1],'+y[1]+')')
        diffli.append(diffdic)
        i1=i1+1
    self.diffli1 = diffli
    diffli2 = []
    locals().update(self.sstate)
    locals().update(self.paramdic)
    for x in self.diffli1:
        tmpdic={}
        for y in x.keys():
#            tmpdic[y] = eval(x[y].tostr())
            str_tmp2 = str(x[y])
            while mreg.search(str_tmp2):
                maout = [por for por in mreg.finditer(str_tmp2)]
                maout.reverse()
                for mato in maout:
                    starts = mato.span()[0]
                    ends = mato.span()[1]
                    expo = mato.group()
                    str_tmp2 = str_tmp2[:starts]+'np.exp(1)'+str_tmp2[ends-1:]
            tmpdic[y] = eval(str_tmp2)

        diffli2.append(tmpdic) 
    self.diffli2 = diffli2
    return self


#This function is needed in population stage 1, at the end
def mk_msstate_subs(self):
    """
    This function takes the manually defined numerical sstate conditions and then replaces
    any @terms with the corresponding substitutions
    """
    _mreg = '@[a-zA-Z]*_bar'
    mreg = re.compile(_mreg)
    tmp_list = deepcopy(self.ssys_list)
    sub_dic = deepcopy(self.nlsubs)
    for i1,x in enumerate(tmp_list):
        while mreg.search(tmp_list[i1]):
            ma = mreg.search(tmp_list[i1])
            str_tmp = ma.group()
            tmp_list[i1] = tmp_list[i1].replace(str_tmp,'('+sub_dic[str_tmp]+')')
    self.ssys_list = deepcopy(tmp_list)
    return self

def mk_mssidic_subs(self):
    """
    This function takes the manually defined numerical sstate's ssidic and then replaces
    any @terms with the corresponding substitutions and evaluates as it goes along
    """
    _mreg = '@[a-zA-Z]*\d*_bar'
    mreg = re.compile(_mreg)
    tmp_list = deepcopy(self.ssili)
    sub_dic = deepcopy(self.nlsubs)
    for i1,x in enumerate(tmp_list):
        while mreg.search(tmp_list[i1][1]):
            ma = mreg.search(tmp_list[i1][1])
            str_tmp = ma.group()
            tmp_list[i1][1] = tmp_list[i1][1].replace(str_tmp,'('+sub_dic[str_tmp]+')')
        locals().update(self.paramdic)
        tmp_dic = {}
        tmp_dic[tmp_list[i1][0]] = eval(tmp_list[i1][1])
        locals().update(tmp_dic)
        # Update ssidic
        self.ssidic.update(tmp_dic)
    self.ssili = deepcopy(tmp_list)
    return self

#This function is needed in population stage 1, at the end
def mk_cfstate_subs(self):
    """
    This function takes the closed form defined numerical sstate conditions and then replaces
    any @terms with the corresponding substitutions
    """
    _mreg = '@[a-zA-Z]*_bar'
    mreg = re.compile(_mreg)
    tmp_list = deepcopy(self.manss_sys)
    sub_dic = deepcopy(self.nlsubs)
    for i1,x in enumerate(tmp_list):
        while mreg.search(tmp_list[i1]):
            ma = mreg.search(tmp_list[i1])
            str_tmp = ma.group()
            tmp_list[i1] = tmp_list[i1].replace(str_tmp,'('+sub_dic[str_tmp]+')')
    self.manss_sys = deepcopy(tmp_list)
    return self

def subs_indic(self):
    '''
    This function replaces indicator function occurrences inside the substitution system
    '''
    list_tmp1 = deepcopy(self.nlsubs_raw1)
    _mreg = '\S{0,1}\s*@I{(?P<cond>.*?)}{(?P<expr>.*?)}'
    mreg = re.compile(_mreg)
    for i1,lino in enumerate(list_tmp1):
        while mreg.search(list_tmp1[i1][1]):
            ma = mreg.search(list_tmp1[i1][1])
            pos, poe = ma.span()
            condi = ma.group('cond')
            expr = ma.group('expr')
            # Expose parameters
            locals().update(self.paramdic)
            if eval(condi):
                list_tmp1[i1][1] = list_tmp1[i1][1][:pos] + expr + list_tmp1[i1][1][poe:]
            else:
                list_tmp1[i1][1] = list_tmp1[i1][1][:pos] + list_tmp1[i1][1][poe:]
    self.nlsubs_raw1 = deepcopy(list_tmp1)
    return self

# Extra population stage factored out, which is needed before steady state calculations
def populate_model_stage_one_a(self, secs):
    # Check and calculate the substitution list and dictionary
    if any([False if 'None' in x else True for x in secs['vsfocs'][0]]):
        # Create the raw nlsubs list 1
        self = mk_subs_dic(self, secs)       
        

# Extra population stage factored out, which is needed before steady state calculations
def populate_model_stage_one_b(self, secs):
    # Check and calculate the substitution list and dictionary
    if any([False if 'None' in x else True for x in secs['vsfocs'][0]]):
        # Deal with indicator functions inside substitutions
        self = subs_indic(self)         
        # Substitute out in @ALL list for expressions, then do expressions
        self = subs_in_subs_all(self)
        self = mk_all(self)
        # Create the raw nlsubs list 2 by replacing substitutions inside substitutions
        self = subs_in_subs(self)
        # Apply steady state transformation where needed
        self = mk_steady(self)
        # Extend the differ out before doing the differ out
        self = ext_differ_out(self)
        # Apply timeshifts where needed
        self = mk_timeshift(self)
        # Make a first differentiation pass for DIFFs inside timeshifters
        self = differ_out(self)
        # Apply timeshifts where needed
        self = mk_timeshift(self)
        # Apply steady state transformation where needed
        self = mk_steady(self)
        # Extend the differ out before doing the differ out
        self = ext_differ_out(self)
        # Make second differentiation pass for remaining DIFFs
        self = differ_out(self)
        # Apply timeshifts where needed
        self = mk_timeshift(self)       
    return self

def populate_model_stage_one_bb(self, secs):
    # Do substitutions inside the numerical steady state list
    # Check and do substitutions
    if all([False if 'None' in x else True for x in secs['vsfocs'][0]]) and\
       all([False if 'None' in x else True for x in secs['manualss'][0]]):
        # Do this only if USE_FOCS has not been used, otherwise ssys_list would be missing
        if '_internal_focs_used' not in dir(self): self = mk_msstate_subs(self)
    # Do substitutions inside the numerical steady state list, but the ssidic
    # Check and do substitutions
    if all([False if 'None' in x else True for x in secs['vsfocs'][0]]) and\
       all([False if 'None' in x else True for x in secs['manualss'][0]]):
        self = mk_mssidic_subs(self)
        # Also save a copy of substituted and evaluated ssili with starting values
        self.template_paramdic['ssili'] = deepcopy(self.ssidic.items())
    # Do substitutions inside the closed form steady state list
    # Check and do substitutions
    if all([False if 'None' in x else True for x in secs['vsfocs'][0]]) and\
       all([False if 'None' in x else True for x in secs['closedformss'][0]]):
        self = mk_cfstate_subs(self)
    # Prepare the nonlinear FOC system but only stripping the raw format
    if all([False if 'None' in x else True for x in secs['focs'][0]]):
        self = premknonlinsys(self,secs)
        # Save for template instantiation
        self.template_paramdic['focs_list'] = self.foceqs
        if all([False if 'None' in x else True for x in secs['vsfocs'][0]]):
            # This takes the stripped system and does @ replacements
            self = premknonlinsys2(self,secs)
        else:
            self.foceqs2 = deepcopy(self.foceqs)
        # Also create a steady state version
        self = mk_steady2(self)
        # Also save a copy of the focs with replaced substitutions, but change timing to Dynare !
        foceqs2 = chg_vtimings(self,deepcopy(self.foceqs2),{'con':[0,1],'endo':[-1,0],'exo':[-1,0]})
        self.template_paramdic['focs_list2'] = deepcopy(self.foceqs2)
        self.template_paramdic['focs_dynare'] = deepcopy(foceqs2)
    else:
        # Save for template instantiation
        self.template_paramdic['focs_list'] = False
    return self


def populate_model_stage_two(self, secs):
    """
    2nd stage population of DSGE model.  Needs Steady State.
    """
    # Creates nonlinear foc system
    if all([False if 'None' in x else True for x in secs['focs'][0]]):
        self = mknonlinsys(self, secs)

    # Creates loglinear system
    if all([False if 'None' in x else True for x in secs['modeq'][0]]):
        llsys_list = mkloglinsys1(secs)
        self.llsys_list = mkloglinsys2(self,llsys_list)
        self.llsys_list = subs_in_loglinsys(self)
        # Save for template instantiation
        self.template_paramdic['llsys_list'] = deepcopy(self.llsys_list)
        self = mksymsys(self) # creates symbolic and numerical system
        self = mkeqtype(self) # creates variance/covariance
    else:
        # Save for template instantiation
        self.template_paramdic['llsys_list'] = False

    # Creates variance/covariance
    if all([False if 'None' in x else True for x in secs['vcvm'][0]]) and\
       'sstate' in dir(self):
        self.sigma = mksigmat(self, secs)
        # Save for template instantiation
        self.template_paramdic['sigma'] = deepcopy(self.sigma)
    else:
        # Save for template instantiation
        self.template_paramdic['sigma'] = False

    return self
