Mars Lander - Puzzle discussion

Could you explain me why you need to substrat (currentAccelleration * 0.5) to the currentPosition ? I don’t understand that. Thanks !

pos = pos_initial + velocitytime + 0.5acceleration*time^2
You will find that formula in physics books or wikipedia.

Fededevi1 added 1acceleration, so he has to subtract 0.5acceleration.

Short answer: This is what it does on their server. :slight_smile:

Long answer: When you are calculating integral on some continuous function with discrete steps, like the simulation is doing, (integral of velocity over time) -> distance; instead of using the function value(velocity) at the start of the time step or at the end of the time step you can use the average velocity between the 2 points. This will usually provide a more precise integration.

Since in my code I update velocity before the position, when I update the position currentVelocity is actually the velocity at the end of the step. By subtracting half of the accelleration I basically remove that half velocity delta to have the average velocity between the 2 steps. The code can be confusing to understand like this but basically it is the same as writing:

   currentAccelleration = thrust + GRAVITY;
   currentVelocity = currentVelocity + currentAccelleration;
   halfStepVelocity = currentVelocity + currentAccelleration * 0.5;
   currentPosition = currentPosition + halfStepVelocity ; 

…I think :wink:

Have Fun!

1 Like

Very clear, thanks !

Thanks, that make sense.

hello i am new in python just a simple question i don’t understand how resolve ‘there is no spoon Episode 1 in python 3’ i tried this : if v_speed < -40:
print (power = 4)
if h_speed > -40:
print (power = 0)
but after this i have any problem can you help me please …

You want to solve There is no spoon or Mars Lander?

Only Level1 using C language, I guess I just don’t get it. I thought something simple would make the program work correctly.

Based on the hint, I used

    if (vSpeed <= -40)
    {
        power = 4;
    }
    
    else if (vSpeed > -40)
    {
        power = 0;
    }

But no matter what I did, the simulation just ran the same way. I don’t want the answer but any hint getting me on the right track would be nice. Thanks.

yep buddy i tried the same code… still dont know whats up… its weird

I had my code in the wrong place.

Hi, I’m coding in python and I want to define two variables “thrust” and “rot” as integers and then simply put as output print(“rot thrust”).

However I’m getting the error:
‘Expected two integers but found ‘rot’ and ‘thrust’’

Does anyone know how to solve this?

Try print("{} {}".format(rot, thrust)) or similar.

1 Like

Or print("%d %d"%(rot,thrust)).

Hi, Thank you for this nice problem.
Since I am a physicist, I would like to signal an error: “a push force equivalent to X m/s² is generated” is faulse. Force unit is kg.m/s2 or N. So in the case of your puzzle, you can say that :
a push force equivalent to an acceleration of X m/s².

Best regards,

Nicolas

4 Likes

Hi,

I’m trying to learn genetic algorithms and I think that this is a good problem for it.
I’m using a single chromosome that I try to mutate to find a good solution.
My genes are (R,P), where R is a rotation (I’m only using 15° increments, so -90, -75…) and P a power (0 or 4).
My fitness function gives a tuple:

  • horizontal distance to the landing site,
  • vertical distance to the landing site,
  • the max between 38 and the abs of the vertical speed
  • the max between 18 and the abs of the horizontal speed
  • the last angle
  • the fuel used
  • (horizontal speed)²+(vertical speed)²

Of course, I’m trying to minimise that.

I’ve got 2 mutations functions. The first one pick a random moment and tries every possibilities with (angle-15,angle,angle+15) and (0 and 4) for the power. I keep track of the moment picked to no do twice the same thing, until I find a best result.
The second mutation function just go through all the genes and change them with a probability of 2/n, where n is the time before landing/crashing.
When my first function pick a moment that has already been tried, it calls the second function.

My problem is that it almost works. I can pass all the tests of mars landers 2, but not each time. Depending on the test, I my have a success rate between 30% and 90%.

The problem is that If I cannot find a good chromosome during the initialisation (since I have more time), I barely manage to get better during the other steps.
I can get around 1000 mutation during the first step and between 50 and 100 for the later steps (of course for the last ones, I can get much better).

I’m using python and I don’t know if I can get faster algorithms.
Do I have to use a small population (like 20 chromosomes) and use a crossing function ?

Should I give more possibilities for the angles and the power ?

And how do you test if you crash ? I have a function that works for Mars Landers 3, but maybe it’s taking too long for this case.

Any help is welcome.
Thanks.

A few thoughts (in no particular order):

Regarding the GA, are you simulating one turn at a time or multiples? The post wasn’t clear on that. I’m assuming you’re looking several turns into the future but if you aren’t, you should be.

A crash in ML2 is easier to detect than in ML3 since there’s no cave component to worry about. You can just look for a negative altitude when you’re not above the landing site, or negative altitude and too high a speed / nonzero angle when you are.

Horizontal and vertical distances are incomplete heuristics for cases like the canyon one… you’re close (horizontally) to the landing site but there’s a mountain in the way, what now?

Finer angle adjustments might help.

Higher speed thresholds might help. I set mine to the highest speed where I could reasonably expect to slow to a safe speed before landing. That way I could make use of some of the high initial starting speeds.

How does your fitness function score a guaranteed crash or landing?

Lastly, a scripted language like Python isn’t well-suited to GAs since they perform best when you can run thousands of generations. Not saying it can’t be done, but it’s easier in a compiled language due to the speed difference.

Thanks for your answer.

I’m simulating every turn until crash/landing. My initial chromosomes have 120 genes, which is enough since you don’t need more than 80 turns, or so, to land.

For the canyon, I think I’ll use some kind of checkpoint, but that’s if I can finish ML2 with a good enough success rate.

I didn’t thought about limiting the speed, but that could be an idea If I give a penalty for high speed, that might help. Because for the one with an initial velocity, sometimes my program fails to reduce enough the speed.

I know I’ve landed if the five first values of my tuple are 0.

I also know that python is not that fast, but since it’s almost working, I think I can optimize it a little bit to increase my success ratio.

I’ve tried using populations. With populations of 20 chromosomes, I can do something like 10 or 11 generations. It’s also “almost” working…

Maybe I’ll have to switch to C or Java, but I really prefer Python.

One other way I can try to do better, is to change my genes by the actual values I’ll get after the simulation. For example genes like [(90,4),(90,4),(-90,4)] will result in [(15,1),(30,2),(15,3)] if I start with (0,0). So maybe, I can replace the genes by the actual states the module will be in. Maybe that can help to get better results after the mutation…

Another approach that’s pretty popular (I use it myself) is to have each chromosome represent the requested change in state rather than the final state. You can bound it to give you only legal moves (+/- 15 and -1, 0, or 1), which might cut down on validation logic later, depending on how you’re doing it. Some people also weight the possible values to make it more likely that they’ll do either a full turn or no turn at all rather than some value in the middle (though a middle value is still possible).

2 Likes

I thought about using “relative” genes but I was afraid that changing one of the first genes would change so drastically the trajectory that it would be rejected even though it was a good “move”.
What I found is that after some iterations, I need to change at least to 2 genes at the time to get a better result.

I think that I can start by using moves with big increments (maybe only using 0, 45 and 90 degrees angles), then, once I have a pretty good trajectory, I can start using smaller angles.

I can also try to add weight to some angles during mutations if most of my mutants fail because of a too big vertical or horizontal speed.

One of the problem I have with more complex validators (with initial speed), is that if you can mess up entirely if you don’t do the correct moves right at the beginning… I think I must do as you said and not only look at the final state for my evaluation function but also at all the states, to help the mutation to correct the trajectory as soon as possible.

And if I keep failing because of a too big horizontal speed, then I should increase the penalty for having a big vertical speed.

Are you using GA for this problem ? Can you tell me roughly how many “generations” you get each turn ? Just so I know if I can keep going with Python.

I’m using a GA with a population of 20 chromosomes made up of 20 genes each. Each gene contains a delta angle, delta power, and ‘number of times to repeat this move’ component, so the end result is 60ish turns worth of movement, on average. With that setup I evolve about 900 potential offspring per turn. That actually seems really low to me when I write it out… now I wonder if I have a bug.