All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.meliorbis.economics.aggregate.ByShockLevelAggregateSolver Maven / Gradle / Ivy

Go to download

A library for solving economic models, particularly macroeconomic models with heterogeneous agents who have model-consistent expectations

There is a newer version: 1.1
Show newest version
package com.meliorbis.economics.aggregate;

import static com.meliorbis.numerics.DoubleArrayFactories.createArrayOfSize;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.ArrayUtils;

import com.meliorbis.economics.model.Model;
import com.meliorbis.economics.model.ModelConfig;
import com.meliorbis.economics.model.ModelException;
import com.meliorbis.economics.model.State;
import com.meliorbis.economics.model.StateWithControls;
import com.meliorbis.numerics.generic.primitives.DoubleArray;
import com.meliorbis.numerics.index.IndexIterator;
import com.meliorbis.numerics.index.impl.Index;
import com.meliorbis.numerics.threading.ComputableRecursiveAction;
import com.meliorbis.utils.Pair;
import com.meliorbis.utils.Timer;
import com.meliorbis.utils.Timer.Stoppable;
import com.meliorbis.utils.Utils;

public abstract class ByShockLevelAggregateSolver, M extends Model>
		extends AggregateSolverBase
{

	public ByShockLevelAggregateSolver(M model_, C config_)
	{
		super(model_, config_);
	}

	/**
	 * Hook called when aggregate expectations have been calculated based on the aggregate transition.
	 * 
	 * Default does nothing
	 * 
	 * @param state_ The state of the calculation
	 */
	protected void afterAggregateExpectationUpdate(S state_)
	{
		
	}

	@Override
	protected Pair, DoubleArray> calculateAggregatePolicies(final S state_)
	{
		
		final Timer timer = new Timer();
		Stoppable stoppable = timer.start("deriveAggTrans");
		
		final DoubleArray newTransition = createArrayOfSize(state_.getAggregateTransition().size());
		final DoubleArray newControlsPolicy = (state_ instanceof StateWithControls) ? createArrayOfSize(((StateWithControls) state_).getCurrentControlsPolicy().size()) : null;
		
		// Create an index with each possible shock value, so they can be
		// iterated over
		List shockSizes = new ArrayList();
		Utils.addLengthsToList(shockSizes, state_.getConfig().getAggregateExogenousStates());
	
		Index aggShocksIndex = new Index(Utils.toIntArray(shockSizes));
	
		IndexIterator shockIterator = aggShocksIndex.iterator();
	
		List actions = new ArrayList();
		
		prepareAggregatePolicyCalculation(state_);
	
		// Fill the implied transition for that level of aggregate shock.
		final int[] fillDims = ArrayUtils.add(
				// It varies by aggregate state...
				Utils.sequence(0, _config.getAggregateEndogenousStateCount()),
				// ...and includes all aggregate states/controls
				newTransition.numberOfDimensions()-1 - _config.getAggregateExogenousStateCount());
		
		// For each potential value of the aggregate shock
		while (shockIterator.hasNext())
		{
			shockIterator.nextInt();
	
			{
				// The combination of aggregate shock values to perform the
				// derivation for
				final int[] currentShockIndexes = shockIterator.getCurrentIndex().clone();
				
				actions.add(()->{
					try
					{
						Stoppable innerDerive = timer.start("innerDerive");
						Pair, DoubleArray> newTransForState = calculateTransitionForShocks(currentShockIndexes, state_);
						innerDerive.stop();
						
						final int[] stateDimSelector = Utils.repeatArray(-1, state_.getConfig().getAggregateEndogenousStateCount() + state_.getConfig().getAggregateControlCount() + currentShockIndexes.length);

						// Be sure to copy the appropriate state's transition
						System.arraycopy(currentShockIndexes, 0, stateDimSelector, _config.getAggregateEndogenousStateCount() + state_.getConfig().getAggregateControlCount(), currentShockIndexes.length);

						
						Stoppable fillTimer = timer.start("fillAggTrans");
						newTransition.at(stateDimSelector).fillDimensions(newTransForState.getLeft(), fillDims);
						fillTimer.stop();
						
						if(newTransForState.getRight() != null) 
						{
							newControlsPolicy.at(stateDimSelector).fillDimensions(newTransForState.getRight(), fillDims);
						}
					} catch (ModelException e)
					{
						//completeExceptionally(e);
					}
				});
			}
		}
	
		Stoppable execTimer = timer.start("gradExec");
		getNumerics().getExecutor().executeAndWait(actions);
		execTimer.stop();
		
		stoppable.stop();
		return new Pair, DoubleArray>(newTransition, newControlsPolicy);
	}
	
	/**
	 * Subclasses should implement this to calculate the  updated forecasting function conditional on the
	 * provided current shocks
	 * 
	 * @param currentShockIndexes_ The current shock to update the forecasting 
	 * function for
	 * @param state_ The current calc state
	 * 
	 * @return The new forecasting function calculated
	 * 
	 * @throws ModelException In the event of Model-Specific failure.
	 */
	abstract protected Pair,DoubleArray> calculateTransitionForShocks(final int[] currentShockIndexes_, S state_) throws ModelException;
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy