Creating the most symmetrical layout based on a range of spans and quantities

(https://techcommunity.microsoft.com/t5/excel/creating-the-most-symmetrical-layout-based-on-a-range-of-spans/m-p/1534955)

I have a complex problem that can be solved by nested loops, which means programming skills which I am not equipped with at this point, but I thought you might have a suggestion on how to use Dynamo to solve that.

Here is the problem:

There is a range of standards element spans and corresponding quantities. I need to find the most symmetrical layout for them.

Fx. if we have the following data in excel

6x6m+3x4.2m+1x3m

then it would generate the most symmetrical combination(s) of layout for them.

3x6m-2x4.2m-1x3m-1x4.2m-3x6m

I do appreciate your help and time in advance.

Best Regards,

Farshid

You want to integrate kind of machine learning tools. You should ask people who can do it well.

You don’t need machine learning for this problem, if I understand it correctly.

“Just” order the objects by their the objects lengths. I assume they have the same width?
E.g:
[6, 6, 6, 6, 6, 6, 4.2, 4.2, 4.2, 1, 1, 1]

Loop over this list and create two new list with alternating elements in each list.

List 1 - [6, 6, 6, 4.2, 4.2, 1] (elements with even indices)
List 2 - [6, 6, 6, 4.2, 1, 1] (elements with odd indices)

Then reverse the second list and concatenate them.

List 1 - [6, 6, 6, 4.2, 4.2, 1]
List 2 - [1, 1, 4.2, 6, 6, 6]

newList = concatenate( List 1, List 2) = [6, 6, 6, 4.2, 4.2, 1, 1, 1, 4.2, 6, 6, 6]

I hope this makes sense?

Something like this in Dynamo?

1 Like

Hi,
That was a brilliant idea, thank you so much! It is really a break through!
The only thing that I am a bit unsure about it is if the number of element types and relevant quantities change then it might not work as perfect as it does in this example.
For instance if we have 4 types of elements and just one instance from one of the types while the other types quantities are more than one.

I do appreciate your time and help once again.

Regards,
Farshid

Thanks for the input

Could you give an example of this?

1 Like

Unless I’ve misinterpreted, the solution by @krbr should still work


Design Script similar to above graph

a = List.TakeEveryNthItem(List.Sort(spn),2,0..1);
b = List.Reverse(List.FirstItem(a));
c = List.Flatten([b,List.LastItem(a)],-1);
1 Like

an approach with Python and divmod() function

lst = [56, 6, 6, 6, 6, 4.2, 4.2, 4.2, 1, 1, 10.8, 22, 22,  22, 22, 22]

lstCount = [[x, lst.count(x) ] for x in set(lst)]
lstCount.sort(key = lambda x : x[0], reverse = True)
lst1 = []
lst2 = []
for x, xcount in lstCount:
	q, mod = divmod(xcount, 2)
	len1 = q + mod
	len2 = q 
	lst1.append([x]*len1)
	lst2.insert(0, [x]*len2)
mergelst = 	lst1 + lst2
flatlst = sum(mergelst, [])

OUT = flatlst

Hi,
Thank you so much for the help, but as I mentioned in my post I am not familiar with the programing stuff jet. Therefore I do appreciate if you could kindly please guide me how to introduce my list in dynamo as input to this code.

Best Regards,
Farshid

Hi,
Thank you for so much your input, I am sorry if I could not present the case clear enough at the first place. But I will do my best to explain the problem as clear as I can this time.
As it is visible in your final listing of spans, the span of 9m is placed at the end of list.

First of all, if we take the 5th item in your list as the center the accumulative sum of the items would be 27 for the items on top and 31 for the items bellow our center element. But if we could switch places for the center item and the last item, then we could get accumulative sum of 26 for the items bellow the center item which mean it would be more symmetrical than our first approach.
Second, if we think of architectural symmetry then when we look from the center to the corners we should have the most possible similar span arrangement on both sides of the center line, which I can think of better arrangements in this specific case.

I hope I could make it Cristal clear this time.

Best Regards,
Farshid

Hi Again,
I managed to input my list so thank you so much for the help provided. I will put this in test and let you know if needed more assistant.

I really appreciate your time and help once again.

Best Regards,
Farshid

Hi Again,
Thank you once again for your efforts to help.
I made a little test with the same list as @Vikram_Subbaiah, except in mm, and I got the following result.
Sym
It seems that it does not make the arrangement around the center item and falls into the same type of problems I mentioned bellow Vikram’s post.

I highly appreciate it if you could take a look and see if you could come up with a solution.

Best Regards,
Farshid

@farshidkaviani Test this and see if it gives better results

a = List.TakeEveryNthItem(List.Sort(spn),2,0..1);
b = List.SortByKey(a, Math.Sum(a<1>))["sorted list"];
c = Math.Sum(b[1])/Math.Sum(List.DropItems(b[0],-1));
d = Math.Sum(b[1])/Math.Sum(List.DropItems(b[0],1));
e = c < d ? List.Flatten([List.Reverse(b[0]),b[1]],-1) : List.Flatten([List.Reverse(b[0]),List.ShiftIndices(b[1],1)],-1);

Edit: Made a change to b in the code (code in image unchanged)

1 Like

Hi Again,
Thank you so much for the update. I am impressed with your work, I ran it through different scenarios and it seems that you did a grate job in distributing spans on the sides of centerline, though when it comes to lists with even number of members and even number of maximum span then it does lay the spans symmetrically on the sides of the centerline. But I guess you have more magics at your disposal and hopefully overcome this last obstacle.
Here are the deferment scenarios I ran through which I hope they can give you a better understanding of what I mean.

Great job so far and looking forward to your last magic to crack it!
I am more than grateful for the help provided!

Best Regards,
Farshid

1 Like

Edit: See if this works

a = List.TakeEveryNthItem(List.Sort(spn),2,0..1);
b = List.SortByKey(a, Math.Sum(a<1>))["sorted list"];
c = Math.Sum(b[0]) == Math.Sum(b[1]) ? 1 : Math.Sum(b[1])/Math.Sum(List.DropItems(b[0],-1));
d = Math.Sum(b[0]) == Math.Sum(b[1]) ? 1 : Math.Sum(b[1])/Math.Sum(List.DropItems(b[0],1));
e = c <= d ? List.Flatten([List.Reverse(b[0]),b[1]],-1) : List.Flatten([List.Reverse(b[0]),List.ShiftIndices(b[1],1)],-1);

Hi,
I am sorry if I forgot to mention you in my reply, but I guess that was because I was not familiar with the workflow. I refer you to my post down her:

Regards,
Farshid

Hello
the problem is that depending on the entry list there may be dozens (or many more) of permutation combinations to find the best solution. Must see, but it might be interesting to work with Generative Design (Autodesk Refinery)

here is a example

Edit script updated
most symmetrical range_v4.dyn (31.6 KB)

5 Likes

You are right. That is why I wrote that he should use machine learning because machine has to calculate all scenarious depends on different plates.

1 Like

Love to see a permutation method for the optimization getting used @c.poupin!

Last I checked the only downfall is that version of the node will be limited to ~12 items to sort fully due to the limits of the number slider and the scope of the problem (a list of 12 items has 12! permutations which is 479,001,600 options). Is the last value in your number slider a reverse of the original list? If not you can add another function to join a list of inputs together for the values (two number sliders) which gets you to 21 or 22 deep lists (22! = 1.1240007e+21) but I recall Python starting to round off for me at after adding a 3rd input.

@farshidkaviani the way I understand this, the issue a bin packing problem. You can learn more about this here: Bin Packing Algorithms (Tutorial 5) D1 EDEXCEL A-Level - YouTube

If you want to stay clear of Refinery/Generatove Design uses, then I recommend you look into the BIM4Stru package by @Dieter_Vermeulen which has a few 1D packing tools, and try to formulate your problem so it works according to that setup. :slight_smile:

2 Likes