07-09-2021 08:46 AM - edited 07-09-2021 08:51 AM
Hello!
I have a program that takes an array of the mass of combination of parts for my project and find the combination of masses closest to the desired total mass. It works pretty well right now, but I have to make it so the final parts are within 5 of each other. I'm having difficulty doing this. I had a while loop that deleted the element that was the closest value if the parts are not within 5 of each other, but it made the program output values that didn't add to the desired total mass. Any suggestions?
I attached my VI file. Sorry its little messy.
Input 16.3 into total mass, and 2 into number of holes to see an example of what I'm trying to explain.
07-09-2021 09:23 AM
@Dom_N wrote:Input 16.3 into total mass, and 2 into number of holes to see an example of what I'm trying to explain.
Did you know that you can set default values for all controls?
After a quick look, your code is not safe due to glaring race conditions and blatant overuse of local variables. I'll have a closer look later once I am on a bigger screen. Lots of other very questionable code (based on logic, not messiness! ;))
Maybe you can explain in a few words what you are trying to do. Your VI is hard to decipher.
07-09-2021 10:05 AM
I am working of a project that requires mass to be added to a balance mass system. The total mass is determined by the frequency the balance mass system runs best at. This VI takes the Total Mass needed and Number of Holes to determines what parts to use to reach the total mass.
Only certain parts with set masses can be added to the balance mass system. I created an array the mass of every combination of these parts (Mass of Combinations in the VI). If there is 2,4,8 Holes it takes subtracts Mass of Combinations from the Total Mass Needed, and the subtracts Mass of Combinations again so that every possible combination of 2 parts is found. Then it finds the closest value from the combination of 2 parts to the desired value.
For example, there 5g, 5.8g, 6.2g are Masses of Combinations. Say you need a Total Mass of 10g. The program does 10-5, 10-5.8, 10-6.2 = 5, 4.2, 3.8 Then 5-5, 5-5.8, 5-6.2, 4.2-5, 4.2- 5.8 ... = 0, -0.8 ... From the last set of values it find the closest value to 0. This index determines what parts to use. Hope this makes the VI make more sense.
07-09-2021 10:44 AM - edited 07-09-2021 02:28 PM
@Dom_N wrote:
Hope this makes the VI make more sense.
OK, so you have an array diagram constant with 37 DBLs (not sure why you have several copies of that same constant elsewhere, e.g. inside one if the inner loops for H=2 and H=4. There is also a copy in an array control! Seems redundant! One set should be sufficient.).
I guess these array values are the available "weights".
It seems we need to pick a subset of those (2, 4, 8, ?) so their sum matches a given input most closely.
Can each value be picked only once or are duplicates allowed?
Even if we select e.g. 8 holes, is it OK to use fewer if the target can be reached equally well?
This is a simple combinatorial problem that can be solved using general algorithms. No need to split the problem based on the number of holes. How fast does this have to be? (With larger input sizes, the problem will become quite expensive!)
Can you explain the two stacks of case structures on the right?
07-12-2021 07:17 AM
Sorry for the late response, I am a new user because I never posted before and you could only make 2 posts in the first 24 hours and didn't have my work laptop to respond.
The two stacks of case structures on the right determine the output of the needed parts to reach the combination. There are two because of Part 1 and Part 2 may not be the same value.
So if Part 1 equals 5 the cluster shows 2.2g Stud and 2.8g Nut.
The number of holes case structures tells it to multiple by 2 for 4 holes, and 4 for 8 holes so that all holes would actually be filled. This is because the balance mass system can either have 1,2,4, or 8 holes filled to keep everything as symmetric as possible. 1 hole can do 5g up to 9.99g, 2 holes can do 10g to 31.6g, 4 holes can do 31.61g to 63.2g, and 8 holes can do 63.21g to 120g. So if the number of holes equals 4 or 8 I divide the Total Mass by 2 or 4 so that 2 parts is all that can be used (For 4 holes there are 2 pairs of 2 parts for a total of 4 parts to fill the 4 holes and the same logic is used for 8 Holes.)
Only 2 different combinations of parts can be used, and duplicates are allowed. So if there is 1 holes there is only 1 part. If there are 2 holes there can be either 2 different parts or 2 of the same parts. If there are 4 holes there can be 4 of the same parts of 2 different pairs(i.e. 5, 5 and 5.8, 5.8). If there are 8 holes there can be 8 of the same parts or 2 different pairs of 4 parts (i.e. 5,5,5,5 and 5.8,5.8,5.8,5.8).
You are right the array of 37 DBLs are the available weights and that the serval copies and a copy in an array control are redundant. Although I think the array control is necessary because other people may need to look at the program and I wanted to try and have it make more sense then just having array constant there. Also I would love to know how to get around the use of local variables.
For the program this VI is apart of I definitely need to cut down on the use of local variables, but I just want to have a mess of wires running across the program because its harder for me and others to understand and follow the program. The Program I'm making needs to be clear and concise because others will need to debug what has gone wrong if something does in the future. (I'm just an intern and will be leaving, and others knowledge of LabVIEW like mine is limited). Any tips with this is greatly appreciated!
07-12-2021 08:11 AM - edited 07-12-2021 12:09 PM
Thanks for the extra details. I'll have a look at it later.
Some quick comments:
@Dom_N wrote:The number of holes case structures tells it to multiple by 2 for 4 holes, and 4 for 8 holes so that all holes would actually be filled. This is because the balance mass system can either have 1,2,4, or 8 holes filled to keep everything as symmetric as possible. 1 hole can do 5g up to 9.99g, 2 holes can do 10g to 31.6g, 4 holes can do 31.61g to 63.2g, and 8 holes can do 63.21g to 120g. So if the number of holes equals 4 or 8 I divide the Total Mass by 2 or 4 so that 2 parts is all that can be used (For 4 holes there are 2 pairs of 2 parts for a total of 4 parts to fill the 4 holes and the same logic is used for 8 Holes.)
So why is the number of holes a control? Since these ranges don't overlap, the weight input uniquely defines the number of holes and should be the only user input. For any given weight, the number of holes is a given.
@Dom_N wrote:
You are right the array of 37 DBLs are the available weights and that the serval copies and a copy in an array control are redundant. Although I think the array control is necessary because other people may need to look at the program and I wanted to try and have it make more sense then just having array constant there. Also I would love to know how to get around the use of local variables.
You want the array as a control if the user is allowed to change the values at random. Since I think the values are fixed, a diagram constant is safer. If you want the user to see the actual values, you can connect an indicator to display the values. In any case, there should be only exactly one instance. What if you notice that one of the values is wrong? Currently you need to make identical changes in four different places and if you forget one by accident, you might get unexpected results that are difficult to debug.
@Dom_N wrote:
For the program this VI is apart of I definitely need to cut down on the use of local variables, but I just want to have a mess of wires running across the program because its harder for me and others to understand and follow the program.
You got that backwards! With local variables, you have no idea what happens and in what order. I.e. a big "mess"! LabVIEW is highly parallel and execution order is only defined by dataflow, not by e.g. horizontal position on the diagram. Have a look at your "2,4,8 Holes Second Array" indicator and the local variable. You cannot guarantees that the local variable only gets read once the indicator has received data. There is a good chance that the local gets read first, meaning it will have stale data from the previous run. Race condition!
When using a wire, you can be 100% sure where the data comes from and where it is going. (If you are using local variables, it might require lots of detective work to figure out what part of the diagram updated it last.) In this particular case, a wire can even eliminate the array indicator entirely, saving you a lot of memory. Much cleaner! No mess!
07-12-2021 08:39 AM
@altenbach wrote:
So why is the number of holes a control? Since these ranges don't overlap, the weight input uniquely defines the number of holes and should be the only user input. For any given weight, the number of holes is a given.
I find how many holes to use and what the total mass needs to be in a different VI that's why I have the number of holes and total mass as inputs. It's not something the user actually ever sees. Because its an input I have it as a control and also for testing purposes.
@altenbach wrote:In any case, there should be only exactly one instance. What if you notice that one of the values is wrong? Currently you need to make identical changes in four different places and if you forget one by accident, you might get unexpected results that are difficult to debug.
I am not entirely sure what you mean here. What values are you talking about?
@altenbach wrote:When using a wire, you can be 100% sure where the data comes from and where it is going. In this particular case, a wire can even eliminate the array indicator entirely, saving you a lot of memory. Much cleaner! No mess!
That makes a lot of sense and would have definitely saved me some time, I'll use more wires in the future for cases like these.
I have updated the VI a bit with all of your notes. Still uses the crazy combination logic 😉
07-12-2021 09:16 AM
Sorry, I'm officially "on vacation" and have limited access to the Web, and even more limited access to LabVIEW, but this sounds like a version of the Knapsack Problem, which I think is one of those "computationally-intractable" (or "Non-Polynomial", or "NP") problems. Might not be trivial ...
Bob Schor
07-12-2021 09:37 AM
I had never heard of the Knapsack Problem, but from looking it up it seems you are exactly correct. It is a very similar problem. Some differences are that it can go above the total mass the goal is just to get as close as possible, as long as the combinations are within 5 of each other. Thanks! I can do some research on this problem now and see where it applies for me.
07-12-2021 12:07 PM
I have a updated the VI to one that is almost completely different. I still have Total Mass and Number of Holes as inputs because they are calculated in a different VI. Should they be changed to indicators? I think there is a lot of improvement from my previous VI. Let me know if it could be even better! Thank you the help!