/* Murat Yildizoglu - Universite Bordeaux IV
 * Montesquieu, FRANCE
 * Copyright (c) 1996-2001 Murat Yildizoglu
 * e-mail: yildi[a_t]u-bordeaux4.fr
 * Permission to use, copy, modify, and distribute this
 * software and its documentation for NON-COMMERCIAL purposes
 * and without fee is hereby granted provided that this
 * copyright notice appears in all copies.
*/

/**
 * An evolutionnary firm close to Nelson and Winter (1982)
 * @version 1.02 16 10 96
 * @author Murat Yildizoglu
 */


import java.util.Random;

public class EvolFirm
{	/** Initializes and computes the firm's caracteristics
	  *	given the caracteristics of the industry to which
	  * it belongs.
	 */

    public EvolFirm(double K0, double prod0, double cost0,
    double p_in, double p_im, double d_in0, double d_im0,
    double sigma_in0, double b0, double delta0, double eta0)
    {
	K=K0;
	prod=prod0;
	cost=cost0;
	r_in=p_in/(K0*d_in0); // p_in: innovation probability
	r_im=p_im/(K0*d_im0); // p_im: imitation probability
	d_in=d_in0;
	d_im=d_im0;
	sigma_in=sigma_in0;
	b=b0;
	delta=delta0;
	eta=eta0;
	r=new Random();

    }

	/** Computes the supply of the firm
	*/
    public double supply()
    {
	return K*prod;
    }

	/** Computes the profit rate on capital
	* @return profit rate
	*/
    public double profit(double Prix)
    {
		return (Prix*prod-(cost+r_in+r_im));

    }

	/** Computes the investment following the rule
	* of Nelson and Winter
	*/
    public void invest(double P, double Supply, double b)
    {
	double invdes=0,invmax=0,ipos=0,inv=0, loans=0;
	double s=supply()/Supply;
	double margin=cost/(P*prod);
	invdes=delta+1-(margin*eta)/(eta-s);
	prf=profit(P);
	if(prf<0) loans=0;
	else loans=b*prf;
	invmax=delta+prf+loans;
	ipos=Math.min(invdes,invmax);
	inv=Math.max(0.0,ipos);
	K*=(1+inv-delta);
    }

	/** Imitative draw
	*/
	public void imitate(double maxprod)
    {
        double tirage=r.nextDouble();
     if ( tirage<=d_im*r_im*K )
	prod=maxprod;
    }

	/** Innovative draw
	*/
    public void innovate()
    {
    	double prd=0;

     double tirage=r.nextDouble();

     if ( tirage<=d_in*r_in*K )
     {
		prd=(r.nextGaussian())*sigma_in+prod;
	}
	if ( prd>prod )
	prod=prd;


    }

	/** Returns the productivity of the firm
	* @param prod
	*/
	public double getprod()
    {
	return prod;
    }

	/** Returns the capital stock
	* @return K
	*/
    public double getKapital()
    {
	return K;
    }

	/** Returns the profit_ratexKapital
	*/

    public double getProfit(double pp)
    {
	return profit(pp)*K;
    }

	/**	Prints on the screen the productivity and capital of the firm
	*/

    public void showFirm()
    {
	System.out.print("Prod= "+prod+"  K= "+K);
    }
    private double prod,K, cost, r_in,
     r_im, d_in, d_im, b, sigma_in, delta, eta,prf;
     private static Random r;
}