How to push stuct data into a stack in julia


#1

Hello,
I have a c++ code where I have created a struct data structure and then I created a function to push struct data into a stack. Now I am wondering can I do the same thing in Julia. The C++ code is given below:

struct SolutionPool {
	int varNameArray[SIZE];
	double varValueArray[SIZE];
	int ObjectiveValue;
	int SolutionNo;
	SolutionPool* SolutionPointer;
};
SolutionPool* SolutionHead = NULL;
SolutionPool* SolutionTemp = NULL;

void SolutionPush(int varName[SIZE], double varValue[SIZE], int ObjectValue, int SolNo) {
	SolutionTemp = new SolutionPool();          //or on the top of the stack
	for (int i = 0; i < SIZE; i++) {
		SolutionTemp->varNameArray[i] = varName[i];
	}
	for (int i = 0; i < SIZE; i++) {
		SolutionTemp->varValueArray[i] = varValue[i];
	}
	SolutionTemp->ObjectiveValue= ObjectValue;
	SolutionTemp->SolutionNo = SolNo;

	SolutionTemp->SolutionPointer = SolutionHead;
	SolutionHead = SolutionTemp;
}

For your information I am very new in Julia and I dont know any alternative used in julia for pointer. Thank you in advance. Your help will be appreciated.


#2

You can start by checking out the push! and pop! functions that allow you to use collections (for example Arrays) as stacks.


#3

Your C++ code constructs a linked list, not a stack. The difference is that linked lists have O(1) insertion, not just amortized O(1), and are incredibly slow to access sequentially (because the CPU can’t hide the memory latency). There are very few cases where linked lists make sense. In julia, a direct translation is even worse because the garbage collector needs to walk your datastructure as well.

Your best bet would be e.g.

struct Solution{SIZE}
    varNameArray::NTuple{SIZE, Int32}
    varValueArray::NTuple{SIZE, Float64}
    ObjectiveValue::Int32
    SolutionNo::Int32
end
const SIZE = 5 #e.g.
const SolutionPool = Vector{Solution{SIZE}}()

SolutionPush(args...) = push!(SolutionPool, Solution(args...))

This will push_back your solution. Julia vectors can replace C++ deque (which your C/C++ code should probably use), at least for sizes that are below a significant fraction of your memory (my experience with push_back and push! into giant vectors is pretty bad, both in C++ and julia, but YMMV).

Consider whether you care about size/memory/speed (switch to Float32) or convenience (switch to Int64). I simply translated your code, but the Int32/Float64 mix is pretty uncommon in julia.

Constant size containers/arrays in julia want to be immutable tuples. Allocation and resize of arrays are effectively foreign function calls into the julia runtime, and the optimizer can’t look inside of these functions; hence, no inlining / constant propagation / inference of sizes / stack allocation (the optimizer can reason about access into arrays).

Or is SIZE very large? Then you might need a Vector instead of an NTuple after all.


#4

Thank you Iostella for your suggestion. I tried the following code:

struct SolutionPool
varNameArray
varValueArray
objectivevalue
SolutionNo
end
a=[0.0 1.0 2.0]
b=[3.0 4.0 5.0]
push!(SolutionPool, a, b, 100.0, 1.0)

But the push! function gives method error. Could you tell me whats wrong with my code?


#5

Thank you @foobar_Iv2 for your translation of my code and explanation of the details.


#6

The push! method is likely defined for Julia’s standard collections, and not on your custom SolutionPool type. To make your example code works, you should implement something like:

function push!(pool::SolutionPool, data::Tuple)
    ...
end

Or otherwise follow @foobar_lv2 suggestion of defining SolutionPool as a Vector, which is simpler.