UML class diagram to code translation

Pages: 12
Hello Everybody,
I have translated the following class diagram (click on the link below) into c++ code. This is my early stage experience indeed for such an implementation from UML class diagram. I am curious to share my improvement. If you have any advice for further improvement, please feel free to drop a line.

https://www.dropbox.com/s/77nmglgmce73f4e/Class_Diagram.png?dl=0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef DATASOURCE_H
#define DATASOURCE_H
class DataSource
{
public:
	double** dataElement = nullptr;
	int nRow, nColumn;
	DataSource();
	~DataSource();

protected:
private:
};
#endif 


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
#include "DataSource.h"
DataSource :: DataSource()
{
	nRow    = 4;
	nColumn = 4;

	double dataFromFile[4][4] = { { 10.0, -1.0, 2.0, 0.0 },
							      { -1.0, 11.0, -1.0, 3.0 },
							      { 2.0, -1.0, 10.0, -1.0 },
							      { 0.0, 3.0, -1.0, 8.0 } };

	allocateData2DbyMalloc(dataElement, nRow, nColumn);
	for (int row = 0; row < nRow; row++)
	{
		for (int col = 0; col < nColumn; col++)
		{
			dataElement[row][col] = dataFromFile[row][col];
		}
	}
}

DataSource :: ~DataSource()
{
	deAllocateData2DbyFree(dataElement, nRow);
	dataElement = nullptr;
}


1
2
3
4
5
6
7
8
9
10
11
12
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
public:
	int numberOfRow, numberOfColumn;
	double** matrixElement = nullptr;
	Matrix();
	virtual ~Matrix();
	void filterDataElement();
};
#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "DataSource.h"
#include "Matrix.h"
#include <iostream>
Matrix :: Matrix()
{
	DataSource  *dataObj  = new DataSource;
	numberOfRow    = dataObj->nRow;
	numberOfColumn = dataObj->nColumn;
	allocateData2DbyMalloc(this->matrixElement, numberOfRow, numberOfColumn);
//..Copy the data from Data Source to Matrix array. Filtarazation of data might necessary before copying. 
	for (int row = 0; row < numberOfRow; row++)
	{
		for (int col = 0; col < numberOfColumn; col++)
		{
			this->matrixElement[row][col] = dataObj->dataElement[row][col]; 
		}
	}
	delete dataObj;
	dataObj = nullptr;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Matrix :: ~Matrix()
{
	deAllocateData2DbyFree(matrixElement, numberOfRow);
	matrixElement = nullptr;
}

#ifndef MATRIXALGORITHM_H
#define MATRIXALGORITHM_H
class MatrixAlgorithm
{
public:
	MatrixAlgorithm();
	~MatrixAlgorithm();
	bool checkDimOfMatrixAndConstrain();
};
#endif 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "Matrix.h"
#include "MatrixAlgorithm.h"
#include <iostream>
MatrixAlgorithm :: MatrixAlgorithm()
{
	Matrix* matObj = new Matrix;
	ItarativeAlgorithm* itarativeAlgorithmObj = new GaussSeidel(matObj->numberOfRow, matObj->numberOfColumn);   
	itarativeAlgorithmObj->matrixA = matObj->matrixElement;
	itarativeAlgorithmObj->vectorB = userInputObj->constrainVector;
	itarativeAlgorithmObj->vectorX = decisionObj->decisionVector;
	itarativeAlgorithmObj->algorithm();
	delete itarativeAlgorithmObj;
	itarativeAlgorithmObj = nullptr;
	delete matObj;
	matObj = nullptr;
}

MatrixAlgorithm :: ~MatrixAlgorithm()
{
}


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
#ifndef ITARATIVE_H
#define ITARATIVE_H
class ItarativeAlgorithm
{
public:
	double** matrixA;

	double* vectorB;
	double* vectorX;
	double* vectorXnext;

	int numberOfRow;
	int numberOfColumn;
	int maxItarationNnumber;

	bool converge;
	double relativeError;
	double maxTolerance;
	double minTolerance;

	ItarativeAlgorithm();
	virtual ~ItarativeAlgorithm();
	void itarativePrint();
	virtual void algorithm();
};
#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "ItarativeAlgorithm.h"
#include <iostream>
ItarativeAlgorithm::ItarativeAlgorithm()
{
	matrixA = nullptr;
	vectorB = nullptr;
	vectorX = nullptr;
	vectorXnext = nullptr;
	converge       = false;
	accuracyTolerance   = 0.0;
	maxItarationNnumber = 10;
}

ItarativeAlgorithm::~ItarativeAlgorithm()
{
}

void ItarativeAlgorithm::algorithm()
{

}


1
2
3
4
5
6
7
8
9
10
11
12
#ifndef GAUSSSEIDEL_H
#define GAUSSSEIDEL_H
#include "ItarativeAlgorithm.h"
class GaussSeidel : public ItarativeAlgorithm
{
public:
	GaussSeidel(int, int);
	~GaussSeidel();
	void algorithm();
};

#endif // !JACOBI_H 

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
#include "GaussSeidel.h"
#include <iostream>
GaussSeidel :: GaussSeidel(int nRow, int nCol) // The reason to define the derive constructor is to observe the deallocation of matrix properly//
{
	this->numberOfRow = nRow;
	this->numberOfColumn = nCol;
}

GaussSeidel :: ~GaussSeidel()
{
}

void GaussSeidel :: algorithm()
{
	int itarationNumber = 0;
	double          sum = 0.0;
	while (itarationNumber < this->maxItarationNnumber)
	{
		std::cout << "Step == " << itarationNumber << std::endl;
			for (int i = 0; i < this->numberOfRow; i++)
			{
				for (int j = 0; j < this->numberOfColumn; j++)
				{
					if (i != j)
						sum = sum + matrixA[i][j] * vectorX[j] * (-1);
				}
				vectorX[i] = (1.0 / matrixA[i][i])*(sum + vectorB[i]); // The only line changed from Jacobi Algorithm
				sum = 0;
			}
		for (int i = 0; i < this->numberOfRow; i++)
		{
			std::cout << vectorX[i] << std::endl;
		}
		itarationNumber = itarationNumber + 1;
	}
	vectorX = nullptr;
}
Last edited on
All the headers are missing.
The driver code is missing.

What do they mean, in the posted scheme, the minuses and the pluses? Private and public?
What does it mean “uses”? Friendship?

- - -
Aside note: I appreciate you attempted to use the tags, but you should select the [ code] tags for the code. The symbol is <>.
Here you go, @shafiul0304034

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
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

using vec = vector<double>;
using matrix = vector<vec>;

vec gaussSeidel( const matrix &A, const vec &B, double EPS, int MAXITER );

//==============================================================================

int main()
{
   matrix A = { { 10.0, -1.0,  2.0,  0.0 },
                { -1.0, 11.0, -1.0,  3.0 },
                {  2.0, -1.0, 10.0, -1.0 },
                {  0.0,  3.0, -1.0,  8.0 } };
   vec B = { 19, 42, 7, 40 };
   vec X = gaussSeidel( A, B, 1.0e-10, 1000 );
   cout << "Solution: X = ";   for ( auto e : X ) cout << e << "  ";
}

//==============================================================================

vec gaussSeidel( const matrix &A, const vec &B, double EPS, int MAXITER )
{
   int N = B.size();
   vec X( N, 0.0 );

   double maxChange = EPS + 1.0;
   int iter = 0;
   while( maxChange > EPS && iter < MAXITER )
   {
      maxChange = 0.0;
      iter++;
      for ( int i = 0; i < N; i++ )
      {
         double Xold = X[i];
         X[i] = B[i];
         for ( int j = 0; j < N; j++ )
         {
            if ( j !=i ) X[i] -= A[i][j] * X[j];
         }
         X[i] /= A[i][i];
         double change = abs( X[i] - Xold );
         if ( change > maxChange ) maxChange = change;
      }
//    cout << iter << '\t' << maxChange << '\n';
   }

// cout << "Converged to tolerance " << maxChange << " in " << iter << " iterations.\n";
   return X;
}


Solution: X = 2  3  1  4  
Last edited on
Hi Enoizat,
yes, minus and plus represent a private and public respectively. Actually the word 'uses' represents a dependency relationship.
Do you have any recommendation regarding the consistency of UML diagram and code?
And what is a dependency relationship?
Matrix and data are two different entities where matrix is dependent on data. This is a dependency relationship.
What does it mean “matrix is dependent on data”?
Could you please provide a compilable example of this “dependency relationship”?
It's tricky to see how your code relates to that UML class diagram.

I don't see object interfaces on your classes, they're structs.

As for the diagram, an arrow indicates inheritance (or possible composition).
I’ve glanced through the summary of UML provided here:
https://en.wikipedia.org/wiki/Unified_Modeling_Language
and that’s probably the most boring thing I’ve come across in my life.

Anyway, what I’ve understood is:
https://en.wikipedia.org/wiki/Class_diagram#Class-level_relationships
1) ‘Dependency’ should be depicted with a dashed line;
2) ‘Inheritance’ requires a visible arrow ending;
3) A ‘normal’ line without visible endings should be ‘binary association’.

Association:
https://en.wikipedia.org/wiki/Association_(object-oriented_programming)
In generic terms, the causation is usually called "sending a message", "invoking a method" or "calling a member function" to the controlled object. Concrete implementation usually requires the requesting object to invoke a method or member function using a reference or pointer to the memory location of the controlled object.


So it seems DataSource should contain a pointer to a Matrix and Matrix should contain a pointer to a DataSource.
Since on DataSource side there’s written 1…*, I think Matrix should contain an array of pointers to DataSource objects.

- - -
I haven’t seen examples of line with filled arrowhead so far, just bordered ones. At first sight, it seems filled arrowheads belongs to another class of diagrams, the “Behavioral UML diagrams”.
Example:
https://en.wikipedia.org/wiki/Activity_diagram

So I think we can assume the ones in OP’s picture represent either inheritance (as kbw suggests), but they should be ‘empty’, or association.
If we take them for inheritance, the scheme becomes pretty convoluted:
1) they are described as «Has a» instead of «Is a»;
2) MatrixAlgorithm should inherit both Matrix and IterativeAlgorithm, but on MatrixAlgorithm side there’s again 1…*, which is hard to interpret here.

- - -
A point where I found no information about is the color, why some of these classes are bordered in red and others in black.

Anyway, a possible interpretation could be:
IterativeAlgorithm inherits GaussSiedal and MatrixAlgorithm inherits Matrix and IterativeAlgorithm.

I’d like to know if I’m misunderstanding or missing something.
Dear Enoizat,
Sorry to be delayed in reply. Thanks for your details word. Well, the relationship between a matrix and data source is defined as:
A matrix can have a lot of data but a lot of data can have only one matrix. Hence the relation from matrix to data is one to many. Aside of this, a matrix is dependent on many data but data are not dependent on matrix. Data can be used just as a vector or anywhere else.

Now let me explain about <<has a>> relationship. <<has a>> relationship from class MatrixAlgorithm to class Matrix indicates an association where many matrix algorithm can use one matrix and many matrix algorithm will select only one iterative algorithm at a time to solve a matrix. The relationship from GaussSiedel to Itarative Algorithm is an inheritance relationship.

The red and black color boxes are just a mistake from me. All of them can be either black or red. if you have any further advise, please feel free to write me.

kind regards
Shafiul

If you have


shafiul0304034 wrote:
I have translated the following class diagram (click on the link below) into c++ code. This is my early stage experience indeed for such an implementation from UML class diagram.
shafiul0304034 wrote:
The red and black color boxes are just a mistake from me. All of them can be either black or red.

shafiul0304034, either
- you have been given the UML diagram as an assignment to turn into C++ code
or
- you are the one who actually worked out the UML diagram (maybe from a C++ code).

In both cases, the lines, arrowheads and styles used don’t comply with what is described in the Wikipedia links I posted.

relationship from class MatrixAlgorithm to class Matrix indicates an association[omissis]… The relationship from GaussSiedel to Itarative Algorithm is an inheritance relationship.

…especially when the same type of line with the same arrowhead is used to express both association and inheritance.

- - -
Now let me explain about <<has a>> relationship.

Let Wikipedia explain «Has a» and «Is a»:

https://en.wikipedia.org/wiki/Has-a
In … object-oriented programming … has-a … is a composition relationship where one object … "belongs to" (is part or member of) another object … In simple words, has-a relationship in an object is called a member field of an object.


https://en.wikipedia.org/wiki/Is-a
In … object-oriented programming … is-a … is a subsumption relationship between abstractions (e.g. types, classes), wherein one class A is a subclass of another class B (and so B is a superclass of A). In other words, type A is a subtype of type B when A's specification implies B's specification.


In both pages there’s a C++ section; in none of them association is mentioned.

- - -
Please, clarify: have you been given an UML diagram to turn into C++?
If so, the UML diagram is wrong and you’re the only one who knows how your teacher creates ‘UML’ diagrams. Perhaps someone else will be able to help you, but that’s far above my capabilities.

Otherwise: are you the author of this diagram? Do you want us to help you turning your C++ code into an UML diagram?
If so, well, your UML diagram has got plenty of errors. Do begin by correcting lines and arrowheads as already pointed out.

- - -
And, at your leisure, please edit the first post and wrap your code into the [ code][/code ] tags instead of the ones you used.
Hi Enoizat,
Thanks for your nice explanation. Yes, I agree, there are a couple of mistake in UML diagram. Indeed I am the author of UML diagram. I am working in numerical mathematics and matrix solver at present. I want to create a matrix solver which can contains many different different algorithm. As I am a beginner, I prefer to follow a good coding standard and prefer to write a good code in C and C++. However, your explanation indeed help me to find a right path. Thanks in advance.

Yes, I am going to edit my code now.

With my kind regards
Shafiul
Yes, I did the editing of my code.
I want to create a matrix solver which can contains many different different algorithm.

Ok. I don’t know math, so I could have a look at the code to check the syntax, but I can’t be of any help for optimization.

- - -
But, since I’ve been haunting this forum for nearly three years, let me come up with some advice:

1) Ask one question (or at least a main question) per thread.
Do not ask about C++ code and UML translation in the same post: people don’t understand what you want.

2) State clearly this program is something you’re doing on your own initiative.
In the beginner's forum it is forbidden to ask about assignments — and actually, if you read the other threads, you can see how many students come here hoping to have their homework done by someone else :-/

3) Add a main() to you code and put it all together into one single block of code, wrapped with [code ][ /code] tags.
If it is only one block and it has a main(), i.e. it is complete, it can be compiled and executed on http://cpp.sh/ with a single click (a gear icon will appear on its right).
That’s probably the most important step to get a good answer ;-)

4) In general, answer people.
Ok, you already do this, but have you seen lastchance’s code above? It sounds rude not to reply at all.


- - -
In general, people are annoyed by double posting on the same topic, but now it seems this thread has been perceived as pointless. But I think you have a good question to ask that could potentially get many good answers.

So, perhaps you could try to:
- abandon this thread
- wait one day
- open another thread, putting a good question and providing your code the right way since the very beginning.

For example (it is merely an example!), you thread heading could be: “A matrix solver with many different algorithms”
The text could be:
«This is my first attempt to implement… <blah blah blah>. How can I improve my code?»
Below your code followed, if there’s room, by an output example.

Days later you can ask about the UML diagram, but perhaps a UML forum would be a better place.
Anyway sometimes it happens some thread doesn’t arouse interest. Nobody knows exactly why.


- - -
there are a couple of mistake in UML diagram

…A couple… Sure… :-)

I wrote and maintained a .m to c++ matrix package for about a decade, written for stable (control problems) matrices (so the handling of badly conditioned inputs was skipped. I skipped a LOT of things for performance, as this stuff was in the 100 mhz single core cpu (and weaker, some were half that) days for a real-time need). I remember some of it, even :)

I know next to nothing about UML, I think I have used it on the average 1 time per decade.

But if you get stuck on the math or performance, I can help.

Be aware that matrix stuff has been done to death. There are multiple high quality libraries out there already. I used one even back then; the point of my tool was actually to convert .m files to .cpp files with the least amount of work, not to re-create the matrix wheel. The parts I wrote were because the library I had wanted you to call 10 functions to set up a multiply, and I had thousands of multiplies. their 10 was slower than my 1 (because I took the aforementioned shortcuts) and a computational engine was born. A bit later I had to find x in ax + xb = c and the library exploded into a pretty full functionality block of code! But it started life filling the gaps in things that matlab coders can do that c++ can't.

the 3 big performance things I found were
- memory management. you often have tons of intermediate results and creating and disposing of memory for those all the time is brutal. Keeping memory ready to go to hold intermediates was critical, whether that is static locals in a routine or something else. This is going to be #1 if you use a library... you still have to deal with this when putting the pieces together into a bigger solver, for something the library does not directly support but has all the parts..

- thinking transposed. The simple matrix multiply wants to go over the rows and columns, but going down a column is expensive for large matrix, it spawns constant page faults. if you can go across the rows in both inputs, its a lot faster. Several algorithms have this issue.

- ** or vector<vector or other 2-d constructs are generally less efficient. At best its identical to single dimension, at worst, its slower. So I always used 1-d memory blocks.

A lot of what I did was C-ish. C++ had a lot of gaps back then, this was PRE stl era, and even after it came out, the new tools lacked performance for a while.
Last edited on
jonnin wrote:
But if you get stuck on the math or performance, I can help.

There’s the code in the first post.
The problem was it was not clear if the OP was asking about the C++ code or the UML diagram. Actually was asking for both :-)
Thank you again, Enoizat. I should follow your advice for the next step. Dear lastchance, thanks for the code. But for now I am focusing on much more on a proper consistency between a UML and implemented code. For some reason, I am planning to work on raw pointer rather than using vector. But thanks for your code.
Please take my advice on * instead of ** if you want to go the pointer route. And let us know what you need next.
there is NOTHING wrong with vector's performance if you use them carefully. Raw * has no advantage, but if you want to go there, you can. Mine was raw * as well.
Last edited on
Hi Jonnin, very nice of you. Well, I did some test to compare the speed performance between vector and pointer allocated by malloc(). For a small matrix vector is even faster. But once I move to large matrix, like 10000x10000 for a iteration of 1000, vector seems a bit slower. malloc is even perform better due to realloc() in each iteration. In real time numerical simulation, the descretization matrix dimension and iteration number can even be bigger. Yes, I am actually thinking to go pointer route of * instead of **. To make my C code GPU compatible.
I am just afraid, you are allocating the memory in one chunk and how big this chunk will be?.
Lets say, i have 10000x10000 dimensional matrix of double type. I want to use single
*. I need 100000000*8 = 800000000 byte = 800MB in total in one chunk. Is it possible to allocate 800MB in one chunk?.

Pages: 12