2008-01-11 14:42:14 +01:00
/*
* Copyright ( C ) 2007 - 2008 Dynare Team
*
* This file is part of Dynare .
*
* Dynare is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Dynare is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Dynare . If not , see < http : //www.gnu.org/licenses/>.
*/
2007-02-22 00:28:16 +01:00
//#define DEBUG
# include <stdio.h>
# include <stdlib.h>
# include <iostream>
# include <sstream>
# include <fstream>
# include "ModelNormalization.hh"
using namespace std ;
2007-06-01 13:43:49 +02:00
Normalization : : Normalization ( const SymbolTable & symbol_table_arg ) :
symbol_table ( symbol_table_arg )
2007-02-22 00:28:16 +01:00
{
//Empty
2007-06-01 13:43:49 +02:00
fp_verbose = false ;
2007-02-22 00:28:16 +01:00
} ;
Normalization : : ~ Normalization ( )
{
//Empty
} ;
void
Normalization : : IM_to_Gr ( int n0 , int prologue , int epilogue , bool * IM , Equation_set * Equation , Variable_set * Variable )
// Create a non-oriented graph of the model from the incidence matrix
{
int i , j , edges , n ;
Edge * e1 ;
# ifdef DEBUG
cout < < " in IM_to_Gr \n " ;
# endif
//Normalize only the earth block (the prologue and the epilogue are still normalized)
n = n0 - prologue - epilogue ;
Equation - > size = n ;
Variable - > size = n ;
Equation - > Number = ( Equation_vertex * ) malloc ( n * sizeof ( Equation_vertex ) ) ;
Variable - > Number = ( Variable_vertex * ) malloc ( n * sizeof ( Variable_vertex ) ) ;
edges = 0 ;
for ( i = 0 ; i < n ; i + + )
{
Equation - > Number [ i ] . First_Edge = NULL ;
Equation - > Number [ i ] . matched = - 1 ;
Variable - > Number [ i ] . matched = - 1 ;
for ( j = 0 ; j < n ; j + + )
{
if ( IM [ ( j + prologue ) * n0 + ( i + prologue ) ] )
{
edges + + ;
e1 = ( Edge * ) malloc ( sizeof ( Edge ) ) ;
e1 - > next = Equation - > Number [ i ] . First_Edge ;
Equation - > Number [ i ] . First_Edge = e1 ;
e1 - > Vertex_Index = j ;
}
}
}
//The maximum number of vertex in each equation is set to the total amount of edges in the model
Equation - > edges = edges ;
# ifdef DEBUG
cout < < " end of IM_to_Gr \n " ;
# endif
}
void
Normalization : : Inits ( Equation_set * Equation )
{
int i ;
# ifdef DEBUG
cout < < " in Inits \n " ;
# endif
eq = eex = 0 ;
IndexUnmatched = Equation - > edges * 2 ;
Local_Heap = ( t_Heap * ) malloc ( IndexUnmatched * sizeof ( t_Heap ) ) ;
for ( i = 0 ; i < Equation - > size ; i + + )
{
Equation - > Number [ i ] . Next_Edge = Equation - > Number [ i ] . First_Edge ;
visited [ i ] = 0 ;
// we put all unmatched vertices from Equation at the other end of the Local_Heap
if ( Equation - > Number [ i ] . matched = = - 1 )
{
Local_Heap [ - - IndexUnmatched ] . u = i ;
# ifdef DEBUG
cout < < i < < " is unmatched \n " ;
# endif
}
}
# ifdef DEBUG
cout < < " end of Inits \n " ;
# endif
}
void
Normalization : : UpdatePath ( Equation_set * Equation , Variable_set * Variable , int i1 , int i2 )
{
int i , j ;
# ifdef DEBUG
cout < < " in UpdatePath \n " ;
# endif
while ( i2 > = 0 )
{
i = Local_Heap [ i2 ] . u ;
j = Local_Heap [ i1 ] . v ;
Variable - > Number [ j ] . matched = i ;
Equation - > Number [ i ] . matched = j ;
i1 = i2 ;
i2 = Local_Heap [ i2 ] . i_parent ;
eex + + ;
}
# ifdef DEBUG
cout < < " end of UpdatePath \n " ;
# endif
}
void
Normalization : : FindAugmentingPaths ( Equation_set * Equation , Variable_set * Variable )
{
// augmenting paths using breadth-first search.
int Bottom ;
int Top ;
int u , i ;
Edge * e , * e2 ;
# ifdef DEBUG
cout < < " in FindAugmentingPaths \n " ;
# endif
// external loop gets unmatched u vertices from far end of array Local_Heap
while ( IndexUnmatched < Equation - > edges * 2 )
{
Top = Bottom = 0 ;
Local_Heap [ Top ] . u = Local_Heap [ IndexUnmatched + + ] . u ;
Local_Heap [ Top ] . i_parent = - 1 ; /* root of BFS tree */
# ifdef DEBUG
cout < < " unmatched u " < < Local_Heap [ Top ] . u < < " will be processed \n " ;
# endif
// Local_Heap processing
while ( Bottom > = Top )
{
u = Local_Heap [ Top + + ] . u ;
e = Equation - > Number [ u ] . First_Edge ;
eq + + ;
// adjacency list scanning
while ( e ! = NULL )
{
if ( ! visited [ Variable - > Number [ e - > Vertex_Index ] . matched ] )
{
// extend tree
Local_Heap [ + + Bottom ] . u = u = Variable - > Number [ e - > Vertex_Index ] . matched ;
Local_Heap [ Bottom ] . i_parent = Top - 1 ;
Local_Heap [ Bottom ] . v = e - > Vertex_Index ;
visited [ u ] = 1 ;
e2 = Equation - > Number [ u ] . Next_Edge ;
eq + + ;
while ( ( e2 ! = NULL ) & & ( Variable - > Number [ e2 - > Vertex_Index ] . matched ! = - 1 ) )
{
e2 = e2 - > next ;
eq + + ;
}
Equation - > Number [ u ] . Next_Edge = e2 ;
if ( e2 ! = NULL )
{
# ifdef DEBUG
cout < < " augmenting path found \n " ;
# endif
// u in the Local_Heap but not the edge to v
Variable - > Number [ e2 - > Vertex_Index ] . matched = u ;
Equation - > Number [ u ] . matched = e2 - > Vertex_Index ;
// now for the rest of the path
UpdatePath ( Equation , Variable , Bottom , Top - 1 ) ;
// temporary cut is emptied
for ( i = 0 ; i < = Bottom ; i + + )
visited [ Local_Heap [ i ] . u ] = 0 ;
Bottom = Top - 1 ;
// to get off from Local_Heap loop
// to get off from adj list scan loop
break ;
}
}
e = e - > next ;
eq + + ;
}
}
}
# ifdef DEBUG
cout < < " end of FindAugmentingPaths \n " ;
# endif
}
void
Normalization : : CheapMatching ( Equation_set * Equation , Variable_set * Variable )
{
int i ;
Edge * e ;
int count = 0 ;
# ifdef DEBUG
cout < < " in CheapMatching Equation->size : " < < Equation - > size < < " \n " ;
# endif
for ( i = 0 ; i < Equation - > size ; i + + )
{
e = Equation - > Number [ i ] . First_Edge ;
while ( e ! = ( Edge * ) NULL )
{
if ( Variable - > Number [ e - > Vertex_Index ] . matched = = - 1 )
{
Variable - > Number [ e - > Vertex_Index ] . matched = i ;
Equation - > Number [ i ] . matched = e - > Vertex_Index ;
# ifdef DEBUG
cout < < i < < " matched to " < < e - > Vertex_Index < < " \n " ;
# endif
count + + ;
break ;
}
e = e - > next ;
}
}
if ( fp_verbose )
cout < < count < < " vertices in Equation were initially matched ( " < < ( float ) 100 * count / Equation - > size < < " %) \n " ;
# ifdef DEBUG
cout < < " end of CheapMatching \n " ;
# endif
}
void
Normalization : : MaximumMatching ( Equation_set * Equation , Variable_set * Variable )
{
# ifdef DEBUG
cout < < " in MaximumMatching \n " ;
# endif
CheapMatching ( Equation , Variable ) ;
Inits ( Equation ) ;
FindAugmentingPaths ( Equation , Variable ) ;
# ifdef DEBUG
cout < < " end of MaximumMatching \n " ;
# endif
}
int
Normalization : : MeasureMatching ( Equation_set * Equation )
{
int size = 0 , i ;
for ( i = 0 ; i < Equation - > size ; i + + )
if ( Equation - > Number [ i ] . matched ! = - 1 )
size + + ;
return size ;
}
void
Normalization : : OutputMatching ( Equation_set * Equation )
{
int i ;
Edge * e1 ;
cout < < " Maximum Matching Results for |Equation|= " < < Equation - > size < < " |Edges|= " < < Equation - > edges < < " \n " ;
for ( i = 0 ; i < Equation - > size ; i + + )
{
if ( Equation - > Number [ i ] . matched ! = - 1 )
cout < < " equation " < < i < < " matched to variable " < < Equation - > Number [ i ] . matched ;
else
cout < < " equation " < < i < < " not matched \n " ;
e1 = Equation - > Number [ i ] . First_Edge ;
while ( e1 ! = NULL )
{
cout < < " " < < e1 - > Vertex_Index ;
e1 = e1 - > next ;
}
cout < < " \n " ;
}
}
void
Normalization : : Gr_to_IM_basic ( int n0 , int prologue , int epilogue , bool * IM , Equation_set * Equation , bool transpose )
{
int i , j , edges , n ;
Edge * e1 ;
n = n0 - prologue - epilogue ;
Equation - > size = n ;
Equation - > Number = ( Equation_vertex * ) malloc ( n * sizeof ( Equation_vertex ) ) ;
edges = 0 ;
if ( transpose )
{
for ( i = 0 ; i < n ; i + + )
{
Equation - > Number [ i ] . First_Edge = NULL ;
Equation - > Number [ i ] . matched = - 1 ;
for ( j = 0 ; j < n ; j + + )
{
if ( ( IM [ ( j + prologue ) * n0 + ( i + prologue ) ] ) & & ( i ! = j ) )
{
edges + + ;
e1 = ( Edge * ) malloc ( sizeof ( Edge ) ) ;
e1 - > next = Equation - > Number [ i ] . First_Edge ;
Equation - > Number [ i ] . First_Edge = e1 ;
e1 - > Vertex_Index = j ;
}
}
}
}
else
{
for ( i = 0 ; i < n ; i + + )
{
Equation - > Number [ i ] . First_Edge = NULL ;
Equation - > Number [ i ] . matched = - 1 ;
for ( j = 0 ; j < n ; j + + )
{
if ( ( IM [ ( i + prologue ) * n0 + ( j + prologue ) ] ) & & ( i ! = j ) )
{
edges + + ;
e1 = ( Edge * ) malloc ( sizeof ( Edge ) ) ;
e1 - > next = Equation - > Number [ i ] . First_Edge ;
Equation - > Number [ i ] . First_Edge = e1 ;
e1 - > Vertex_Index = j ;
}
}
}
}
//The maximum number of vertex in each equation is set to the total amount of edges in the model
Equation - > edges = edges ;
# ifdef DEBUG
cout < < " end of IM_to_Gr \n " ;
# endif
}
void
Normalization : : Gr_to_IM ( int n0 , int prologue , int epilogue , bool * IM , simple * Index_Equ_IM , Equation_set * Equation , bool mixing , bool * IM_s )
{
int i , j , n , l ;
Edge * e1 , * e2 ;
Equation_set * Equation_p ;
simple * Index_Equ_IM_tmp = ( simple * ) malloc ( n0 * sizeof ( * Index_Equ_IM_tmp ) ) ;
bool * SIM = ( bool * ) malloc ( n0 * n0 * sizeof ( bool ) ) ;
# ifdef DEBUG
cout < < " in Gr_to_IM \n " ;
# endif
n = n0 - prologue - epilogue ;
if ( mixing )
{
for ( i = 0 ; i < n0 * n0 ; i + + )
SIM [ i ] = IM_s [ i ] ;
for ( i = 0 ; i < n0 ; i + + )
Index_Equ_IM_tmp [ i ] . index = Index_Equ_IM [ i ] . index ;
for ( i = 0 ; i < n ; i + + )
{
/*Index_Var_IM[j+prologue].index=Index_Var_IM_tmp[Equation->Number[j].matched+prologue].index;*/
if ( fp_verbose )
cout < < " Equation->Number[ " < < i < < " ].matched= " < < Equation - > Number [ i ] . matched < < " \n " ;
Index_Equ_IM [ i + prologue ] . index = Index_Equ_IM_tmp [ Equation - > Number [ i ] . matched + prologue ] . index ;
for ( j = 0 ; j < n0 ; j + + )
SIM [ ( i + prologue ) * n0 + j ] = IM_s [ ( Equation - > Number [ i ] . matched + prologue ) * n0 + j ] ;
}
for ( i = 0 ; i < n0 * n0 ; i + + )
IM [ i ] = SIM [ i ] ;
}
else
{
for ( i = 0 ; i < n0 * n0 ; i + + )
SIM [ i ] = IM [ i ] ;
for ( i = 0 ; i < n0 ; i + + )
Index_Equ_IM_tmp [ i ] . index = Index_Equ_IM [ i ] . index ;
for ( j = 0 ; j < n ; j + + )
{
if ( fp_verbose )
cout < < " Equation->Number[ " < < j < < " ].matched= " < < Equation - > Number [ j ] . matched < < " \n " ;
Index_Equ_IM [ j + prologue ] . index = Index_Equ_IM_tmp [ Equation - > Number [ j ] . matched + prologue ] . index ;
for ( i = 0 ; i < n0 ; i + + )
SIM [ ( i ) * n0 + j + prologue ] = IM [ ( i ) * n0 + Equation - > Number [ j ] . matched + prologue ] ;
}
for ( i = 0 ; i < n0 * n0 ; i + + )
IM [ i ] = SIM [ i ] ;
}
free ( SIM ) ;
free ( Index_Equ_IM_tmp ) ;
if ( mixing )
Gr_to_IM_basic ( n0 , prologue , epilogue , IM , Equation , true ) ;
else
{
// In this step we :
// 1) get ride of the edge from the equation to its explain variable
// 2) resort the equation in the order of the matched variable
// 3) transpose the graph
// in order to get the oriented graph needed to find strong connex components
Equation_p = ( Equation_set * ) malloc ( sizeof ( Equation_set ) ) ;
Equation_p - > size = Equation - > size ;
Equation_p - > edges = Equation - > edges ;
Equation_p - > Number = ( Equation_vertex * ) malloc ( n * sizeof ( Equation_vertex ) ) ;
for ( i = 0 ; i < n ; i + + )
{
Equation_p - > Number [ i ] . First_Edge = NULL ;
Equation_p - > Number [ i ] . Next_Edge = NULL ;
}
for ( i = 0 ; i < n ; i + + )
{
l = Equation - > Number [ i ] . matched ;
e1 = Equation - > Number [ l ] . First_Edge ;
while ( e1 ! = NULL )
{
if ( e1 - > Vertex_Index ! = i )
{
j = e1 - > Vertex_Index ;
if ( Equation_p - > Number [ j ] . First_Edge ! = NULL )
{
Equation_p - > Number [ j ] . Next_Edge - > next = ( Edge * ) malloc ( sizeof ( Edge * ) ) ;
Equation_p - > Number [ j ] . Next_Edge = Equation_p - > Number [ j ] . Next_Edge - > next ;
}
else
{
Equation_p - > Number [ j ] . First_Edge = ( Edge * ) malloc ( sizeof ( Edge * ) ) ;
Equation_p - > Number [ j ] . Next_Edge = Equation_p - > Number [ j ] . First_Edge ;
}
Equation_p - > Number [ j ] . Next_Edge - > next = NULL ;
Equation_p - > Number [ j ] . Next_Edge - > Vertex_Index = i ;
}
e2 = e1 - > next ;
free ( e1 ) ;
e1 = e2 ;
}
}
for ( i = 0 ; i < n ; i + + )
{
Equation - > Number [ i ] . matched = Equation_p - > Number [ i ] . matched ;
Equation - > Number [ i ] . First_Edge = Equation_p - > Number [ i ] . First_Edge ;
Equation - > Number [ i ] . Next_Edge = Equation_p - > Number [ i ] . Next_Edge ;
}
free ( Equation_p - > Number ) ;
free ( Equation_p ) ;
}
# ifdef DEBUG
cout < < " end of Gr_to_IM \n " ;
# endif
}
void
Normalization : : Free_Equation ( int n , Equation_set * Equation )
{
//free unused space
Edge * e1 , * e2 ;
int i ;
for ( i = 0 ; i < n ; i + + )
{
e1 = Equation - > Number [ i ] . First_Edge ;
while ( e1 ! = NULL )
{
e2 = e1 - > next ;
e1 = e2 ;
}
}
free ( Equation - > Number ) ;
free ( Equation ) ;
}
void
Normalization : : Free_Other ( Variable_set * Variable )
{
//free unused space
free ( Local_Heap ) ;
free ( Variable - > Number ) ;
free ( Variable ) ;
free ( visited ) ;
}
void
Normalization : : Free_All ( int n , Equation_set * Equation , Variable_set * Variable )
{
Free_Equation ( n , Equation ) ;
Free_Other ( Variable ) ;
}
void
Normalization : : ErrorHandling ( int n , bool * IM , simple * Index_Equ_IM )
{
int i , j , k , k1 , k2 ;
for ( i = 0 ; i < n ; i + + )
{
k = 0 ;
for ( j = 0 ; j < n ; j + + )
k + = ( int ) IM [ j * n + Index_Equ_IM [ i ] . index ] ;
if ( k = = 0 )
cout < < " the variable " < < getnamebyID ( eEndogenous , Index_Equ_IM [ i ] . index ) < < " does not appear in any equation \n " ;
for ( j = i + 1 ; j < n ; j + + )
{
k1 = k2 = 0 ;
for ( k = 0 ; k < n ; k + + )
{
k1 = k1 + ( int ) ( IM [ Index_Equ_IM [ i ] . index * n + k ] ! = IM [ Index_Equ_IM [ j ] . index * n + k ] ) ;
k2 = k2 + ( int ) IM [ Index_Equ_IM [ i ] . index * n + k ] ;
}
if ( ( k1 = = 0 ) & ( k2 = = 1 ) )
cout < < " the variable " < < getnamebyID ( eEndogenous , Index_Equ_IM [ i ] . index ) < < " is the only endogenous variable in equations " < < Index_Equ_IM [ i ] . index + 1 < < " and " < < Index_Equ_IM [ j ] . index + 1 < < " \n " ;
}
}
}
2007-06-01 13:43:49 +02:00
2007-02-22 00:28:16 +01:00
void
2007-06-01 13:43:49 +02:00
Normalization : : Set_fp_verbose ( bool ok )
{
fp_verbose = ok ;
}
bool
2007-02-22 00:28:16 +01:00
Normalization : : Normalize ( int n , int prologue , int epilogue , bool * IM , simple * Index_Equ_IM , Equation_set * Equation , bool mixing , bool * IM_s )
{
int matchingSize , effective_n ;
2007-06-01 13:43:49 +02:00
int save_fp_verbose = fp_verbose ;
2007-02-22 00:28:16 +01:00
fp_verbose = 0 ;
Variable_set * Variable = ( Variable_set * ) malloc ( sizeof ( Variable_set ) ) ;
# ifdef DEBUG
cout < < " in Normalize \n " ;
# endif
visited = ( bool * ) malloc ( n * sizeof ( * visited ) ) ;
IM_to_Gr ( n , prologue , epilogue , IM , Equation , Variable ) ;
MaximumMatching ( Equation , Variable ) ;
matchingSize = MeasureMatching ( Equation ) ;
effective_n = n - prologue - epilogue ;
2007-06-01 13:43:49 +02:00
fp_verbose = save_fp_verbose ;
if ( matchingSize < effective_n & & fp_verbose )
2007-02-22 00:28:16 +01:00
{
2007-06-01 13:43:49 +02:00
cout < < " Error: dynare could not normalize the model. \n The following equations: \n - " ;
int i ;
for ( i = 0 ; i < Equation - > size ; i + + )
if ( Equation - > Number [ i ] . matched = = - 1 )
cout < < i < < " " ;
cout < < " \n and the following variables: \n - " ;
for ( i = 0 ; i < Variable - > size ; i + + )
if ( Variable - > Number [ i ] . matched = = - 1 )
cout < < symbol_table . getNameByID ( eEndogenous , Index_Equ_IM [ i ] . index ) < < " " ;
cout < < " \n could not be normalized \n " ;
//ErrorHandling(n, IM, Index_Equ_IM);
//system("PAUSE");
2007-02-22 00:28:16 +01:00
exit ( - 1 ) ;
}
2007-06-01 13:43:49 +02:00
if ( matchingSize > = effective_n )
2007-02-22 00:28:16 +01:00
{
2007-06-01 13:43:49 +02:00
Gr_to_IM ( n , prologue , epilogue , IM , Index_Equ_IM , Equation , mixing , IM_s ) ;
if ( fp_verbose )
{
OutputMatching ( Equation ) ;
for ( int i = 0 ; i < n ; i + + )
cout < < " Index_Equ_IM[ " < < i < < " ]= " < < Index_Equ_IM [ i ] . index /*<< " == " "Index_Var_IM[" << i << "]=" << Index_Var_IM[i].index*/ < < " \n " ;
}
2007-02-22 00:28:16 +01:00
}
Free_Other ( Variable ) ;
# ifdef DEBUG
cout < < " end of Normalize \n " ;
# endif
2007-06-01 13:43:49 +02:00
if ( matchingSize < effective_n )
return ( 0 ) ;
else
return ( 1 ) ;
2007-02-22 00:28:16 +01:00
}