Presume we have a set of 12 objects, lets say {1,2,3,4,5,6,7,8,9,10,11,12}. We must break this set into 4 smaller ones composed of three objects, so that the largest sum and smallest sum of these four sets is minimized. We must find this difference. In our example, {1,7,12},(3,8,9},{4,5,10},{2,6,11}. These four sets satisfy the problem since their sums are 20 and 19, meaning a delta of 1, our answer.
How can one solve this problem for any arbitrary 12 values?
I've tried enumerating all partitions of said set into 4 sets of 3, and finding one with the optimal score. However, time is of the essence, and so I was wondering how one would approach this problem in Java
I don't have exact code on me right now, but what it essentially was was 9 nested for loops, where the first three that nest are one set, the next three are the next set, the last three are another set, and the three left overs are another set. I used a 2D array so that values would be in score[i][0] and score[i][1] would act as an indicator to let me know if that value in score[i][0] had already been placed into a set.
This of course gets tedious and inefficient.
You could easily simplify the problem by finding the values that the sums must approach for a better optimisation :
For instance, in your simple case (1,2...12), then the total sum of every terms is 78. Thus, Each groups must have a sum very close to 78/4=19.
So, let's try a very simple algorithm :
- compute TOTAL_SUM = SUM(terms)
- compute TARGET_SUM = TOTAL_SUM / number(terms)
- set DELTA=0
- loop {
- Try to split terms in groups where TARGET_SUM - DELTA <= SUM <= TARGET_SUM + DELTA
- if a solution is found, exit
- DELTA = DELTA + 1
- }
Ok, I did not helped you much with this "Try to split..." step. But it should look like you own solution, except that you have additional constraints which can help you to speed up the process.
Hope this helps.
Related
I have came across a subset sum problem recently. I was able to solve it for smaller arrays using Java earlier, but in this case I have really no idea what should I do. Brute force and recurrence is probably not an option, as I came across out of memory problem.
So, let's say we have an array of {2500, 3200, 3300}. We are looking for the sum closest to the desired number K = 135000. The main difference is that we can use numbers from the array multiple times.
Ok, if we can use them multiple times, then we can change it to more "traditional" way - just divide K by each of these numbers - that is 54, 42 and 40 - and create a new array, which has those numbers the number of times received from dividing. It would be {2500, 2500, 2500, ... , ... 3300, 3300} and the new array would have the length of 136. Now this is much more than 3.
So - how to solve the closest subset sum problem, where we can pick more than 2 numbers from the array of 136 elements or more using Java?
The thing I want to get is not only the closest sum, but also a list of elements which gave that sum.
I heard and was reading about dynamic programing, approximation algorithms and genetic algorithms, but unfortunately I have no idea about those. I did genetic algorithm for a different case some time ago, but I am not sure how to use it in this case.
Any ideas? I will be really glad for help.
I am not going to solve it for you. but I'll give you the key ideas in pseudocode (aka Python).
We start with a state that represents the following statement: "I don't know how to arrive to any numbers. The best thing I can generate is 0. I have not yet processed the fact that I could get to 0."
In data:
can_generate = set()
todo = [0]
best = 0
K = 135000
What we will do is, while anything is in todo, take off a value, see if it is new to us. If it is, we might update best, and possibly add new values to todo. Like this:
while len(todo):
value = todo.pop()
if value not in can_generate:
can_generate.add(value)
if abs(K-value) < abs(K-best):
best = value
if value < K:
for term in [2500, 3200, 3300]:
todo.append(value + term)
Now that we know the values in can_generate, we search backwards to find how to get there.
answer = []
while 0 < best:
for term in [3300, 3200, 2500]:
if best - term in can_generate:
answer.append(term)
best -= term
break
It occurs to me that using random number to select the parentslike gambling roulettemaybe workalbe.Let me explain it using an example in find the max value of function.The example is shown below:
1.Imagine that we have already generated n random individual and calculated their function value.We named the individual 'j' Xj,and its function value name is f(Xj).And we find and name the max function-value maxValue.
2.It is clear that the fitness of individual j is f(Xj)/maxValue.We can name it g(Xj).And then we calculate all fitness of individuals.
3.The next step is to find the parents.(We abandon the individual whose fitness values is less than 0) .A classtic way is gambling roulette.The chance of selecting Xjand Xkis g(Xj)*g(Xk)/[g(X1)+g(X2)+...+g(Xn)]^2.
My idea is
1.select two random individual Xj and Xk
2.generate a random number rn in range of 0~1.
3.if rn is less than g(Xj)and g(Xk)(the fitness of Xj and Xk),then they are able to reproduce.Then crossover and mutate.
4.judge whether we have generated enough child individuals,if so,end.
else,repeat 1-3.
The chance of selecting Xjand Xk is g(Xj)*g(Xk)/n^2,which is similar to gambling roulette.Consider that both denominator of two chance are constant value,they are equal in a certain way.
double randomNumToJudge=Math.random();//generate a random number to judge with the fitness
int randomMother=(int)(Math.random()*1000);
int randomFather=(int)(Math.random()*1000);//random generate parents
if((randomNumToJudge<=individualArray[generation][randomFather].fitnessValue)
&&(randomNumToJudge<=individualArray[generation][randomMother].fitnessValue))
//if the number is less than both fitness of parents,they are permited to reproduce.
{
Individual childIndividual=individualArray[generation][randomFather].crossOverAndMutate(individualArray[generation][randomFather], individualArray[generation][randomMother]);
//Crossover and mutate and generate child individual
individualArray[generation+1][counter]=childIndividual;//add childIndividual to tha Array.
counter++;//the count of individual number in child generation
}
I test this way in a java code.The function is x + 10sin(5x) + 7cos(4x), x∈[0,10).I generate 100 generation and the individual number in a generation is 1000.
Its result is correct.
In a certain execution,in the 100th generation,i find the best individual is 7.856744175554171,and the best function value is 24.855362868957645.
I have tested for 10 times.Every result is accurate to 10 decimal places in 100th generation.
So is this way workable?Is this way already been thought by others?
Any comments are appreciated ^#^
PS:Pardon my poor english-_-
Please note I have edited this answer.
From point 2, I am assuming your target fitness is 1. Your algorithm will likely never fully converge (find a local minima). This is because your random value range (0~>1) does not change even if your fitnesses do.
Note that this does not mean better fitnesses are not created; they will be. But there will be a sharp decline in the speed at which better fitnesses are created due to the fact that you are checking for fitnesses (random 0~>1).
Consider this example where all fitnesses have converged to be high:
[0.95555, 0.98888, 0.92345, 0.92366]
Here, all values are very likely to satisfy randomNumToJudge<=fitness. This means any of the values are equally likely to be chosen as a parent. You do not want this - you want the best values to have a higher chance of being chosen.
Your algorithm could be amended to converge properly if you set your randomNumToJudge to have a range of (median fitness in population ~> 1), though this still is not optimal.
Alternative Method
I recommend implementing the classic roulette wheel method.
The roulette wheel method assigns to each individual a probability of being chosen as a parent based on how "fit" they are. Essentially, the greater the fitness, the the bigger the slice of the wheel the individual will occupy and the higher the chance a random number will choose this position on the wheel.
Example Java code for roulette wheel selection
trying to figure out following problem:
Given a set S of N positive integers the task is to divide them into K subsets such that the sum of the elements values in every of the K subsets is equal.
I want to do this with a set of values not more than 10 integers, with values not bigger than 10 , and less than 5 subsets.
All integers need to be distributed, and only perfect solutions (meaning all subsets are equal, no approximations) are accepted.
I want to solve it recursively using backtracking. Most ressources I found online were using other approaches I did not understand, using bitmasks or something, or only being for two subsets rather than K subsets.
My first idea was to
Sort the set by ascending order, check all base cases (e.g. an even distribution is not possible), calculate the average value all subsets have to have so that all subsets are equal.
Going through each subset, filling each (starting with the biggest values first) until that average value (meaning theyre full) is achieved.
If the average value for a subset can't be met (undistributed values are too big etc.), go back and try another combination for the previous subset.
Keep going back if dead ends are encountered.
stop if all dead ends have been encountered or a perfect solution was found.
Unfortunately I am really struggling with this, especially with implementing the backtrack and retrying new combinations.
Any help is appreciated!
the given set: S with N elements has 2^N subsets. (well explained here: https://www.mathsisfun.com/activity/subsets.html ) A partition is is a grouping of the set's elements into non-empty subsets, in such a way that every element is included in one and only one of the subsets. The total number of partitions of an n-element set is the Bell number Bn.
A solution for this problem can be implemented as follows:
1) create all possible partitions of the set S, called P(S).
2) loop over P(S) and filter out if the sum of the elements values in every subsets do not match.
I want to find a multiplication of two numbers in Java recursively with using only Addition, Subtraction and Comparison. So, I googled and I found Egyptian Algorithm that meets the question requirement.
However, I'm not sure how to find the multiplication result after we reach the base case.
Example:
13 x 30
1 -- 30
2 -- 60
4 -- 120
8 -- 240 //we stop here because the double of 8 is larger than 13
To find the result we add the numbers from the left column that equals 13 which they are 1+4+8 and on the other hand we add its opposite numbers from the right column which they are 30+120+240 = 390 which is the result.
But now how to do last part programatically ? how to check which numbers to add? I hope you guys get my point. Hints only needed.
Here's pseudocode to solve the problem:
function egyptian(left, right)
prod := 0
while (left > 0)
if (left is odd)
prod := prod + right
left := halve(left)
right := double(right)
return prod
Basically, instead of waiting until the end, it is easier to check each row of the template as it is created and sum if it belongs in the output. I discuss this algorithm at my blog.
Do a loop through the created results in reverse order
Each time, if your multiplicant remainder (which starts equal to your multiplicant) is larger than the number in the left column, subtract the left column from your multiplicant and add the right column to your result (which starts at zero).
You might have found this Wikipedia article.
Have a look at the last part of the section called "decomposition". You'll find the sub-algorithm you have to implement.
Okay, I did it using Brute Force Algorithm. It's a BigO-(n) though. I'm sure there is more efficient way to implement it. For now. I'm settling with this.
Thanks guys!
As you can see from the title, I'm busy programming a little programm for visualizing fractals in Java. Anybody who deals with fractals will come to the point where he/she searches for a solution to get these stupid "bands" away, when you just colour a pixel by the number of iterations it took to escape.
So I searched for a more advanced colouring algorithm, finding the "normalized iteration count". The formula I'm using is:
float loc = (float) 1 - Math.log(Math.log(c.abs())) / Math.log(2);
Everybody on the Internet is so happy about this algorithm, everybody uses it, everbody gets great results. Except me. I thought, this algorithm should provide a float between 0 and 1. But that doesn't happen. I did some calculations and came to the conclusion, that this algorithm only works for c.abs() >= Math.E && c.abs() <= Math.exp(2) (that is Math.E * Math.E).
In numbers this means, my input into this equation has to be between about 2.718 and 7.389.
But a complex number c is considerd to tend towards infinity when its magnitude gets greater than 2. But for any Input smaller than Math.E, I get a value greater than one. And for any number greater than Math.exp(2), it gets negative. That is the case if a complex number escapes really fast.
So please tell me: what am I doing wrong. I'm desperate.
Thanks.
EDIT:
I was wrong: the code I posted is correct, I just
1. used it the wrong way and so it didn't provide the right output.
2. had to set the bailout value of the mandelbrot/julia algorithm to 10, otherwise I would've got stupid bands again.
Problem solved!
As you've already discovered, you need to increase the bailout radius before smoothing will look right.
Two is the minimum length that a coordinate can have such that when you square it and add the initial value, it cannot result in a smaller length. If the previous length was 2.0, and you squared it, you'd have a length of 4.0 (pointing in whichever direction), and the most that any value of c could reduce that by is 2.0 (by pointing in precisely the opposite direction). If c were larger than that then it would start to escape right away.
Now, to estimate the fractional part of the number of iterations we look at the final |z|. If z had simply been squared and c not added to it, then it would have a length between 2.0 and 4.0 (the new value must be larger than 2.0 to bail out, and the old value must have been less than 2.0 to have not bailed out earlier).
Without c, taking |z|'s proportional position between 2 and 4 gives us a fractional part of the number of iterations. If |z| is close to 4 then the previous length must have been close to 2, so it was already close to bailing out in the previous iteration and the smoothed result should be close to the previous iteration count to represent that. If it's close to 2, then the previous iteration was further from bailing out, and so the smoothed result should be closer to the new iteration count.
Unfortunately c messes that up. The larger c is, the larger the potential error is in that simple relationship. Even if the old length was nearly at 2.0, it might have landed such that c's influence made it look like it must have been smaller.
Increasing the bailout mitigates the effect of adding c. If the bailout is 64 then the resulting length will be between 64 and 4096, and c's maximum offset of 2 has a proportionally smaller very impact on the result.
You have left out the iteration value, try this:
float loc = <iteration_value> + (float) 1 - Math.log(Math.log(c.abs())) / Math.log(2);
The iteration_value is the number of iterations which yielded c in the formula.