A practical case for vectors in a class

Hi everyone. I am doing a simulation with firm dynamics. Each firm has some attributes. Firms are born or dead each year. I am trying to create a class of firm with some vectors inside as attributes, then in main function create a lot of firms. It does not work properly. Can someone tell me whether I am doing it in a good way please?
There is not much information in your post. Do you have a specific problem?
It sounds like you have the right idea, use classes! I am not sure what else to say.
Last edited on
I cannot find a good example of a class including several vectors. I only found some about a vector of class objects, which is different from my case. Could anyone please cite an example?
If you know how to use a vector outside a class, you know how to use one inside a class.

Provide code that illustrates the difficulty you are having.
It shouldn't matter how many vectors you use. What you are talking about is very standard practice.

What I do suggest is that you fully encapsulate the vector. You shouldn't let the outside world now you've implemented your storage using a vector. Then, if want to change your mind, there is no ripple. I am always careful to avoid returning iterators for or references to the vectors inside classes.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <vector>

class SomeVectors
{
public:
    std::vector<int> integers;
    std::vector<char> characters;   
};

int main()
{
    SomeVectors myVectors;

    myVectors.integers.push_back(10);
    myVectors.characters.push_back('a'); 

    return 0;
}


Does that help?
Last edited on
@monad

Personally, I would not do that!

I believe you should never directly call the member functions of a classes data members. integers and characters, like all other data members, should be private. You are exposing the inner workings of the SomeVectors class.
Last edited on
Thank you all, that does help. Actually, the dynamics of value of some vectors should be related to others. Let's say here output is always related to capital. The evolution of one value leads the dynamics of the other attributes. I have written some codes like following, separated in two files:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef agent_h
#define agent_h

using namespace std;

class agent
{
	vector<double> output;
	vector<double> capital;

public:
	agent(output, capital)
	{
		output = capital*1.5;
	}

}

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "agent.h"
#include <iostream>
#include <vector>

using namespace std;
//using std::cout;

int main()
{
	agent firm1;
	
	double x = 1.0;
	for (int i = 0; i < 10; i++)
	{
		firm1.capital.push_back(10.0 + x++);
		firm1.output.pushback();
	}

	return 0;
}


However, I think there are some big problems. Cannot build solution. Could you please help me?
output and capital are private members of agent. main not being a member function of agent, it doesn't have access to those private members.

Why would a firm/agent have multiple values for capital?
should i put inside of class definition a function that defines the relation between output and capital?

a firm of type "agent" has its capital value vary according time, so as the output relying on capital.
andywestken wrote:
@monad

Personally, I would not do that!

I believe you should never directly call the member functions of a classes data members. integers and characters, like all other data members, should be private. You are exposing the inner workings of the SomeVectors class.

Generally I would agree with you. I was just trying to give a simple visual of "a class including several vectors". I admit that my post lacks apparently vital explanation.

dekeenfrance wrote:
However, I think there are some big problems.

Yes.

As cire noted, output and capital are private, which means that only members of agent or friends of agent are allowed to access them. Specifically, main is not allowed to call push_back on them. One solution is to write a member function that wraps push_back, because the member function will have access.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// agent.h

#ifndef agent_h
#define agent_h

// agent needs to know about vectors.
#include <vector>

// This should not be here as it pollutes the global namespace.
using namespace std;

class agent
{
    // Private by default.
    vector<double> output;
    vector<double> capital;

public:
    /*agent(output, capital) // these parameter names are the same name as
    {                        //your members and they don't have a types.
        // I do not know what you are trying to do here.
        output = capital*1.5;
    }*/

    // Here we are declaring two new functions that operate on our members.
    void appendCapital(double n);
    void appendOutput(double n);
}

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
// agent.cpp

#include "agent.h"

// Here is our implementation of agent's member functions.
void agent::appendCapital(double n)
{
    capital.push_back(n);
}

void agent::appendOutput(double n)
{
    output.push_back(n);
}


Now You can do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "agent.h"
#include <iostream>
#include <vector>

using namespace std;
//using std::cout;

int main()
{
    agent firm1;
	
    double x = 1.0;
    for (int i = 0; i < 10; i++)
    {
        // I am not sure what if you can increment a double like that. Help?
        firm1.appendCapital(10.0 + x++);
    }

    return 0;
}


Hope this gets you on track.
Last edited on
Thanks cire for your advice. Thanks monad for your code correction. That does make it much clearer.

For the part:
1
2
3
4
5
6
public:
    /*agent(output, capital) // these parameter names are the same name as
    {                        //your members and they don't have a types.
        // I do not know what you are trying to do here.
        output = capital*1.5;
    }*/

actually I wanted to build a constructor. Then I can call it from the main function as many time as necessary to create a lot of firms of the same type. Meanwhile, each object (of type "agent" here) includes several vectors. And I wanted the value of output related directly to capital. So once capital is initialized, output will be initialized automatically.

Do I need to put the relation :output = capital*1.5;" in the function member of class? Should I declare the vectors "output" and "capital" in public if I use constructor?

For the last comment, you are right, we cannot increment a double like that. I just wanted to show that the value of capital varies each time (actually depending on profit and borrowing, not included here), and output at the same time.

Here's a short working example with, IMHO, a better class name and strategy for information storage.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <vector>
#include <iomanip>
#include <random>

class AgentHistory
{
public:
    AgentHistory( const std::vector<double>& capital ) ;

    std::ostream& printOn(std::ostream & os ) const ;

private:

    struct info  // sounds as if it might be appropriate to store a date here as well.
    {
        double capital ;
        double output ;

        explicit info ( double capital_value ) 
            : capital(capital_value), output(capital_value*1.5)
        {}
    };

    std::vector<info> history ;
};

AgentHistory::AgentHistory(const std::vector<double>& capital)
{
    for ( auto i= capital.begin(); i!= capital.end() ;  ++i )
        history.push_back(info(*i)) ;
}

std::ostream& AgentHistory::printOn(std::ostream& os) const
{
    const unsigned column_width = 12 ;
    os << std::setw(column_width) << std::left << "   Capital" << "   Output\n" ;

    os << std::setprecision(2) << std::fixed << std::right ;

    for ( auto i = history.begin(); i!= history.end(); ++i )
        os << std::setw(column_width) << i->capital 
           << std::setw(column_width) << i->output << '\n' ;
    return os ;
}

int main()
{
    std::srand(time(0)) ;

    unsigned min = 20000 ;
    unsigned max = 1000000 ;
    std::vector<double> capital ;

    for ( unsigned i = 0;  i < 20;  ++i )
        capital.push_back( std::rand()%(max-min) + min ) ;

    AgentHistory h(capital) ;

    h.printOn(std::cout) ;
}


[ edit: vector parameters should have been constant references. ]
Last edited on
Note that cire's example is in C++0x.

For C++03 you would replace the first occurrence of auto with std::vector<double>::const_iterator and the second with std::vector<info>::const_iterator. You would also use cstdlib instead of random.

cire, would you object to the changes when restricted to C++03?

Edit: To be clear, I am really just trying to understand your intention behind using the auto keyword.
Last edited on
To be clear, I am really just trying to understand your intention behind using the auto keyword.


Using auto makes things easier to read (and write,) and it's very simple to change if your compiler doesn't support it.
Hello everyone, first of all thanks a lot to cire and monad for your help. That did give me an idea to develop my programming.

Actually, I want to make a simulation of “endogenous” process with 10 firms during 20 periods (each firm with 3 vectors “capital, output, net income” and a static “time”). In the simulation, I only give an initial value of capital, from which each firm has its output value (capital*1.5), and receives a net income value (made from a series of normally distributed values in the main function). After period 1 (marked by time =0), in each period, each firm receives a net income that affects its capital level. If its capital becomes negative, the firm dies. Otherwise, it survives.

I have written some codes, including a function “PushPush” to determine each element of the three vectors for every period. However, there are still a lot of problems. Could you please help me correct it? I didnot include codes for output results. That's for later.

Here are the codes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//agent.h

#ifndef agent_h
#define agent_h

#include <vector>

class CAgent
{
public:
	CAgent(const std::vector<double>& capital) ;

private:
	struct info
	{
		std::vector<double> capital;
		std::vector<double> output;
		std::vector<double> net_income;
		static int time; // mark time in simulation

		explicit info(double initial_capital, double income.begin()) // constructor
			:capital[0](initial_capital), output[0](initial_capital*1.5), net_income[0](income.begin())
		{}

		void PushPush(); // function of firms' capital, output evolution
	};
	std::vector<info> history;
};


#endif 


1
2
3
4
5
6
7
8
9
10
//agent.cpp

#include"agent.h"


void CAgent::info::PushPush()
{
	capital.push_back(capital[time-1] + net_income[time-1]);
	output.push_back(capital[time]);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//main.cpp

#include "agent.h"
#include <iostream>
#include <vector>
#include <random>

using namespace std;
//using std::cout;

int main()
{
	double initial_capital;
	vector<double> income;
	
	int period = 20; // number of periods in simulation
	int number = 10; // number of firms in simulation
	static int time = 0; // mark time in simulation

	// generate a random value to decide whether the firm survives
	const int nrolls = 1000; // number of random values
	std::default_random_engine generator;
	std::normal_distribution<double> distribution(1.0, 2.0);
	for(int i = 0; i < nrolls; i++)
		double norm_dist = distribution(generator);

	for(int i = 0; i < period; i++) // define net income of each firm in each period
		income[i] = norm_dist[i];

	for(int n = 0; n < number; n++) // create 10 firms in simulation with name: firm_#
		CAgent firm_(n+1)(capital_value = 10);

	for(time = 0; time < period; time++) // simulation continues during predefined periods
		for(int n = 0; n < number; n++)
			if(capital[time-1] > 0)
				void PushPush();
	
	return 0;
}
For a moment, compare the structure info in my previous example:

1
2
3
4
5
6
7
8
9
   struct info 
    {
        double capital ;
        double output ;

        explicit info ( double capital_value ) 
            : capital(capital_value), output(capital_value*1.5)
        {}
    };


to yours in the current code:

1
2
3
4
5
6
7
8
9
10
11
12
13
	struct info
	{
		std::vector<double> capital;
		std::vector<double> output;
		std::vector<double> net_income;
		static int time; // mark time in simulation

		explicit info(double initial_capital, double income.begin()) // constructor
			:capital[0](initial_capital), output[0](initial_capital*1.5), net_income[0](income.begin())
		{}

		void PushPush(); // function of firms' capital, output evolution
	};


Where, in both cases, the class member looks like:
std::vector<info> history;

The reason, in my example, for using 1 double for each of capital and output (as opposed to a vector of doubles) is that info was intended to be a sort of snapshot in time. The plurality of those moments is expressed by the definition of history. Your snapshot includes vectors for capital and company, which implies that there should be more than one of each value for each snapshot in time. Now, perhaps that's what you want. I tend to think it isn't.

That said, you've got quite a few logical and syntax errors in the code.

On lines 24 to 25 of main.cpp norm_dist only exists for the duration of one iteration of the for loop. Each iteration you create a new variable, assign it the value from distribution(generator) and discard it.

As a result, norm_dist isn't defined on line 28 (and was never defined as an array or vector type, so the indexing makes no sense.)

I don't know what you think you're doing on line 31.

The time variable defined on line 18 of main.cpp is not the same as the time variable declared on line 19 of agent.h (which is never actually defined.)

In the info constructor, it would appear you meant for the income parameter to be a vector, not a double. Keep in mind, the example I showed you was a minimal one. You need methods to modify your agent class, and the agent is responsible for constructing the info objects.

It doesn't appear you've actually implemented the agent's constructor anywhere.

Do one thing and get that thing working before you try to put everything together.
Last edited on
Thank you cire for your explanation. For your first comment, I really am confused.

just to ask: can we declare vectors as members of a class, and initialize only the first element of each vector via the constructor?

If yes, how can we achieve that? Only by using a pointer?

Thanks a lot for your reply.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <vector>

 struct vecWrap
{
    std::vector<int> member ;

    vecWrap( ) : member(1, -1) {} ;
    vecWrap(int value ) : member( 1, value) {} ;
};


 void print( const vecWrap & v )
 {
     std::cout << "{ " ;
     for ( unsigned i=0 ; i < v.member.size() ;  ++ i )
        std::cout << v.member[i] << ' ' ;

     std::cout << "}\n" ;
 }

 int main()
 {
     vecWrap vw1 ;
     vecWrap vw2(1000) ;

     std::cout << "vw1: " ;
     print(vw1) ;

     std::cout << "v2w: " ;
     print(vw2) ;
 
vw1: { -1 }
v2w: { 1000 }


http://www.cplusplus.com/reference/stl/vector/vector/
(2nd constructor on the page)
Last edited on
Thanks! That was very clear!

Last edited on
Topic archived. No new replies allowed.