Fading a Line Exponentially - python
I'd like to fade the values of a line on the Y axis using a gradient that I can control.
This is a simplified version of what I'm trying right now.
y_values = [1,1,1,1,1,1]
for i, y in enumerate(y_values): #i is the index, y is the individual y value
perc = i/(len(y_values)-1) #progress the fade by the percentage of the index divided by the total values
amt = y * perc #y is the target amount to decrease multiplied by index percentage
y -= amt
print(i,y)
This code produces this:
1.0
0.8
0.6
0.4
0.2
0.0
It's creating a linear fade, but how do I increase the fade with an exponential fade like this?
Thank you!
To make exponential fading, you have to provide two coefficients to provide initial factor 1.0 at the start value x1 and desired final factor k at the end of interval x2
y = y * f(x)
f(x) = A * exp(-B * x)
So
f(x1) = 1 = A * exp(B * x1)
f(x2) = k = A * exp(B * x2)
divide the second by the first
k = exp(B * (x2 - x1))
ln(k) = B * (x2 - x1)
so
B = ln(k) / (x2 - x1)
A = exp(B * x1)
Example for x1 = 0, x2 = 60, k = 0.01
B = -4.6/60= -0.076
A = 1
f(x) = exp(-0.076*x)
f(30) = exp(-0.076*20) = 0.1
Python example:
import math
def calcfading(x1, x2, ratio):
B = math.log(ratio) / (x2 - x1)
A = math.exp(B * x1)
return A, B
def coef(x, fade):
return fade[0]*math.exp(x*fade[1])
cosine = [[x, math.cos(x)] for x in range(0, 11)]
print(cosine)
print()
fade = calcfading(0, 10, 0.01)
expcosine = [[s[0], coef(s[0], fade)*s[1]] for s in cosine]
print(expcosine)
Related
Orbit spirals using 4th order Yoshida integration
I am attempting to use the 4th order Yoshida integration technique to model the orbit of satellites in circular orbits around the Earth. However, the orbits I achieve spiral away quite quickly. The code for a Moon like satellite is below. Interestingly, the particles behaved when I use Euler method, however, I wanted to try a more accurate method. The issue could then be within how I have implemented the algorithm itself. I have tried using the gravitational parameter rather then computing G*M, but this did not help. I also reduced the time-step, messed around with units, printed and checked values for various integration steps etc., but could not find anything. Is this the correct use of this algorithm? G = 6.674e-20 # km^3 kg^-1 s^-2 day = 60.0 * 60.0 * 24.0 # length of day dt = day / 10.0 M = 5.972e24 # kg N = 1 delta = np.random.random(1) * 2.0 * np.pi / N angles = np.linspace(0.0, 2.0 * np.pi, N) + delta rad = np.random.uniform(low = 384e3, high = 384e3, size = (N)) x, y = rad * np.cos(angles), ringrad * np.sin(angles) vx, vy = np.sqrt(G*M / rad) * -np.sin(angles), np.sqrt(G*M / rad) * np.cos(angles) def update(frame): global x, y, vx, vy, dt, day positions.set_data(x, y) # coefficients q = 2**(1/3) w1 = 1 / (2 - q) w0 = -q * w1 d1 = w1 d3 = w1 d2 = w0 c1 = w1 / 2 c2 = (w0 + w1) / 2 c3 = c2 c4 = c1 # Step 1 x1 = x + c1*vx*dt y1 = y + c1*vy*dt dist1 = np.hypot(x1, y1) acc1 = -(G*M) / (dist1**2.0) dx1 = x1 - x dy1 = y1 - y accx1 = (acc1*dx1)/(x1) accy1 = (acc1*dy1)/(y1) vx1 = vx + d1*accx1*dt vy1 = vy + d1*accy1*dt # Step 2 x2 = x1 + c2*vx1*dt y2 = y1 + c2*vy1*dt dist2 = np.hypot(x2, y2) acc2 = -(G*M) / (dist2**2.0) dx2 = x2 - x1 dy2 = y2 - y1 accx2 = (acc2*dx2)/(x2) accy2 = (acc2*dy2)/(y2) vx2 = vx1 + d2*accx2*dt vy2 = vy1 + d2*accy2*dt # Step 3 x3 = x2 + c3*vx2*dt y3 = y2 + c3*vy2*dt dist3 = np.hypot(x3, y3) acc3 = -(G*M) / (dist3**2.0) dx3 = x3 - x2 dy3 = y3 - y2 accx3 = (acc3*dx3)/(x3) accy3 = (acc3*dy3)/(y3) vx3 = vx2 + d3*accx3*dt vy3 = vy2 + d3*accy3*dt # Full step x = x3 + c4*vx3*dt y = y3 + c4*vy3*dt vx = vx3 vy = vy3 return positions
How to increase FPS in ursina python
I want to create survival games with infinite block terrain(like Minecraft). So i using ursina python game engine, you can see it here So i using perlin noise to create the terrain with build-in ursina block model. I test for first 25 block and it work pretty good with above 100 FPS, so i start increase to 250 block and more because I want a infinite terrain. But i ran to some problem, when i increase to 100 block or more, my FPS start to decrease below 30 FPS (With i create just one layer). Here is my code: #-------------------------------Noise.py(I got on the github)------------------------- # Copyright (c) 2008, Casey Duncan (casey dot duncan at gmail dot com) # see LICENSE.txt for details """Perlin noise -- pure python implementation""" __version__ = '$Id: perlin.py 521 2008-12-15 03:03:52Z casey.duncan $' from math import floor, fmod, sqrt from random import randint # 3D Gradient vectors _GRAD3 = ((1,1,0),(-1,1,0),(1,-1,0),(-1,-1,0), (1,0,1),(-1,0,1),(1,0,-1),(-1,0,-1), (0,1,1),(0,-1,1),(0,1,-1),(0,-1,-1), (1,1,0),(0,-1,1),(-1,1,0),(0,-1,-1), ) # 4D Gradient vectors _GRAD4 = ((0,1,1,1), (0,1,1,-1), (0,1,-1,1), (0,1,-1,-1), (0,-1,1,1), (0,-1,1,-1), (0,-1,-1,1), (0,-1,-1,-1), (1,0,1,1), (1,0,1,-1), (1,0,-1,1), (1,0,-1,-1), (-1,0,1,1), (-1,0,1,-1), (-1,0,-1,1), (-1,0,-1,-1), (1,1,0,1), (1,1,0,-1), (1,-1,0,1), (1,-1,0,-1), (-1,1,0,1), (-1,1,0,-1), (-1,-1,0,1), (-1,-1,0,-1), (1,1,1,0), (1,1,-1,0), (1,-1,1,0), (1,-1,-1,0), (-1,1,1,0), (-1,1,-1,0), (-1,-1,1,0), (-1,-1,-1,0)) # A lookup table to traverse the simplex around a given point in 4D. # Details can be found where this table is used, in the 4D noise method. _SIMPLEX = ( (0,1,2,3),(0,1,3,2),(0,0,0,0),(0,2,3,1),(0,0,0,0),(0,0,0,0),(0,0,0,0),(1,2,3,0), (0,2,1,3),(0,0,0,0),(0,3,1,2),(0,3,2,1),(0,0,0,0),(0,0,0,0),(0,0,0,0),(1,3,2,0), (0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0), (1,2,0,3),(0,0,0,0),(1,3,0,2),(0,0,0,0),(0,0,0,0),(0,0,0,0),(2,3,0,1),(2,3,1,0), (1,0,2,3),(1,0,3,2),(0,0,0,0),(0,0,0,0),(0,0,0,0),(2,0,3,1),(0,0,0,0),(2,1,3,0), (0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0), (2,0,1,3),(0,0,0,0),(0,0,0,0),(0,0,0,0),(3,0,1,2),(3,0,2,1),(0,0,0,0),(3,1,2,0), (2,1,0,3),(0,0,0,0),(0,0,0,0),(0,0,0,0),(3,1,0,2),(0,0,0,0),(3,2,0,1),(3,2,1,0)) # Simplex skew constants _F2 = 0.5 * (sqrt(3.0) - 1.0) _G2 = (3.0 - sqrt(3.0)) / 6.0 _F3 = 1.0 / 3.0 _G3 = 1.0 / 6.0 class BaseNoise: """Noise abstract base class""" permutation = (151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9, 129,22,39,253,9,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180) period = len(permutation) # Double permutation array so we don't need to wrap permutation = permutation * 2 randint_function = randint def __init__(self, period=None, permutation_table=None, randint_function=None): """Initialize the noise generator. With no arguments, the default period and permutation table are used (256). The default permutation table generates the exact same noise pattern each time. An integer period can be specified, to generate a random permutation table with period elements. The period determines the (integer) interval that the noise repeats, which is useful for creating tiled textures. period should be a power-of-two, though this is not enforced. Note that the speed of the noise algorithm is indpendent of the period size, though larger periods mean a larger table, which consume more memory. A permutation table consisting of an iterable sequence of whole numbers can be specified directly. This should have a power-of-two length. Typical permutation tables are a sequnce of unique integers in the range [0,period) in random order, though other arrangements could prove useful, they will not be "pure" simplex noise. The largest element in the sequence must be no larger than period-1. period and permutation_table may not be specified together. A substitute for the method random.randint(a, b) can be chosen. The method must take two integer parameters a and b and return an integer N such that a <= N <= b. """ if randint_function is not None: # do this before calling randomize() if not hasattr(randint_function, '__call__'): raise TypeError( 'randint_function has to be a function') self.randint_function = randint_function if period is None: period = self.period # enforce actually calling randomize() if period is not None and permutation_table is not None: raise ValueError( 'Can specify either period or permutation_table, not both') if period is not None: self.randomize(period) elif permutation_table is not None: self.permutation = tuple(permutation_table) * 2 self.period = len(permutation_table) def randomize(self, period=None): """Randomize the permutation table used by the noise functions. This makes them generate a different noise pattern for the same inputs. """ if period is not None: self.period = period perm = list(range(self.period)) perm_right = self.period - 1 for i in list(perm): j = self.randint_function(0, perm_right) perm[i], perm[j] = perm[j], perm[i] self.permutation = tuple(perm) * 2 class SimplexNoise(BaseNoise): """Perlin simplex noise generator Adapted from Stefan Gustavson's Java implementation described here: http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf To summarize: "In 2001, Ken Perlin presented 'simplex noise', a replacement for his classic noise algorithm. Classic 'Perlin noise' won him an academy award and has become an ubiquitous procedural primitive for computer graphics over the years, but in hindsight it has quite a few limitations. Ken Perlin himself designed simplex noise specifically to overcome those limitations, and he spent a lot of good thinking on it. Therefore, it is a better idea than his original algorithm. A few of the more prominent advantages are: * Simplex noise has a lower computational complexity and requires fewer multiplications. * Simplex noise scales to higher dimensions (4D, 5D and up) with much less computational cost, the complexity is O(N) for N dimensions instead of the O(2^N) of classic Noise. * Simplex noise has no noticeable directional artifacts. Simplex noise has a well-defined and continuous gradient everywhere that can be computed quite cheaply. * Simplex noise is easy to implement in hardware." """ def noise2(self, x, y): """2D Perlin simplex noise. Return a floating point value from -1 to 1 for the given x, y coordinate. The same value is always returned for a given x, y pair unless the permutation table changes (see randomize above). """ # Skew input space to determine which simplex (triangle) we are in s = (x + y) * _F2 i = floor(x + s) j = floor(y + s) t = (i + j) * _G2 x0 = x - (i - t) # "Unskewed" distances from cell origin y0 = y - (j - t) if x0 > y0: i1 = 1; j1 = 0 # Lower triangle, XY order: (0,0)->(1,0)->(1,1) else: i1 = 0; j1 = 1 # Upper triangle, YX order: (0,0)->(0,1)->(1,1) x1 = x0 - i1 + _G2 # Offsets for middle corner in (x,y) unskewed coords y1 = y0 - j1 + _G2 x2 = x0 + _G2 * 2.0 - 1.0 # Offsets for last corner in (x,y) unskewed coords y2 = y0 + _G2 * 2.0 - 1.0 # Determine hashed gradient indices of the three simplex corners perm = self.permutation ii = int(i) % self.period jj = int(j) % self.period gi0 = perm[ii + perm[jj]] % 12 gi1 = perm[ii + i1 + perm[jj + j1]] % 12 gi2 = perm[ii + 1 + perm[jj + 1]] % 12 # Calculate the contribution from the three corners tt = 0.5 - x0**2 - y0**2 if tt > 0: g = _GRAD3[gi0] noise = tt**4 * (g[0] * x0 + g[1] * y0) else: noise = 0.0 tt = 0.5 - x1**2 - y1**2 if tt > 0: g = _GRAD3[gi1] noise += tt**4 * (g[0] * x1 + g[1] * y1) tt = 0.5 - x2**2 - y2**2 if tt > 0: g = _GRAD3[gi2] noise += tt**4 * (g[0] * x2 + g[1] * y2) return noise * 70.0 # scale noise to [-1, 1] def noise3(self, x, y, z): """3D Perlin simplex noise. Return a floating point value from -1 to 1 for the given x, y, z coordinate. The same value is always returned for a given x, y, z pair unless the permutation table changes (see randomize above). """ # Skew the input space to determine which simplex cell we're in s = (x + y + z) * _F3 i = floor(x + s) j = floor(y + s) k = floor(z + s) t = (i + j + k) * _G3 x0 = x - (i - t) # "Unskewed" distances from cell origin y0 = y - (j - t) z0 = z - (k - t) # For the 3D case, the simplex shape is a slightly irregular tetrahedron. # Determine which simplex we are in. if x0 >= y0: if y0 >= z0: i1 = 1; j1 = 0; k1 = 0 i2 = 1; j2 = 1; k2 = 0 elif x0 >= z0: i1 = 1; j1 = 0; k1 = 0 i2 = 1; j2 = 0; k2 = 1 else: i1 = 0; j1 = 0; k1 = 1 i2 = 1; j2 = 0; k2 = 1 else: # x0 < y0 if y0 < z0: i1 = 0; j1 = 0; k1 = 1 i2 = 0; j2 = 1; k2 = 1 elif x0 < z0: i1 = 0; j1 = 1; k1 = 0 i2 = 0; j2 = 1; k2 = 1 else: i1 = 0; j1 = 1; k1 = 0 i2 = 1; j2 = 1; k2 = 0 # Offsets for remaining corners x1 = x0 - i1 + _G3 y1 = y0 - j1 + _G3 z1 = z0 - k1 + _G3 x2 = x0 - i2 + 2.0 * _G3 y2 = y0 - j2 + 2.0 * _G3 z2 = z0 - k2 + 2.0 * _G3 x3 = x0 - 1.0 + 3.0 * _G3 y3 = y0 - 1.0 + 3.0 * _G3 z3 = z0 - 1.0 + 3.0 * _G3 # Calculate the hashed gradient indices of the four simplex corners perm = self.permutation ii = int(i) % self.period jj = int(j) % self.period kk = int(k) % self.period gi0 = perm[ii + perm[jj + perm[kk]]] % 12 gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]] % 12 gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]] % 12 gi3 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1]]] % 12 # Calculate the contribution from the four corners noise = 0.0 tt = 0.6 - x0**2 - y0**2 - z0**2 if tt > 0: g = _GRAD3[gi0] noise = tt**4 * (g[0] * x0 + g[1] * y0 + g[2] * z0) else: noise = 0.0 tt = 0.6 - x1**2 - y1**2 - z1**2 if tt > 0: g = _GRAD3[gi1] noise += tt**4 * (g[0] * x1 + g[1] * y1 + g[2] * z1) tt = 0.6 - x2**2 - y2**2 - z2**2 if tt > 0: g = _GRAD3[gi2] noise += tt**4 * (g[0] * x2 + g[1] * y2 + g[2] * z2) tt = 0.6 - x3**2 - y3**2 - z3**2 if tt > 0: g = _GRAD3[gi3] noise += tt**4 * (g[0] * x3 + g[1] * y3 + g[2] * z3) return noise * 32.0 def lerp(t, a, b): return a + t * (b - a) def grad3(hash, x, y, z): g = _GRAD3[hash % 16] return x*g[0] + y*g[1] + z*g[2] class TileableNoise(BaseNoise): """Tileable implemention of Perlin "improved" noise. This is based on the reference implementation published here: http://mrl.nyu.edu/~perlin/noise/ """ def noise3(self, x, y, z, repeat, base=0.0): """Tileable 3D noise. repeat specifies the integer interval in each dimension when the noise pattern repeats. base allows a different texture to be generated for the same repeat interval. """ i = int(fmod(floor(x), repeat)) j = int(fmod(floor(y), repeat)) k = int(fmod(floor(z), repeat)) ii = (i + 1) % repeat jj = (j + 1) % repeat kk = (k + 1) % repeat if base: i += base; j += base; k += base ii += base; jj += base; kk += base x -= floor(x); y -= floor(y); z -= floor(z) fx = x**3 * (x * (x * 6 - 15) + 10) fy = y**3 * (y * (y * 6 - 15) + 10) fz = z**3 * (z * (z * 6 - 15) + 10) perm = self.permutation A = perm[i] AA = perm[A + j] AB = perm[A + jj] B = perm[ii] BA = perm[B + j] BB = perm[B + jj] return lerp(fz, lerp(fy, lerp(fx, grad3(perm[AA + k], x, y, z), grad3(perm[BA + k], x - 1, y, z)), lerp(fx, grad3(perm[AB + k], x, y - 1, z), grad3(perm[BB + k], x - 1, y - 1, z))), lerp(fy, lerp(fx, grad3(perm[AA + kk], x, y, z - 1), grad3(perm[BA + kk], x - 1, y, z - 1)), lerp(fx, grad3(perm[AB + kk], x, y - 1, z - 1), grad3(perm[BB + kk], x - 1, y - 1, z - 1)))) #--------------------------Math.py(For InverseLefp)-------------------------------- def Clamp(t: float, minimum: float, maximum: float): """Float result between a min and max values.""" value = t if t < minimum: value = minimum elif t > maximum: value = maximum return value def InverseLefp(a: float, b: float, value: float): if a != b: return Clamp((value - a) / (b - a), 0, 1) return 0 #-----------------------------Game.py(Main code)---------------------- from ursina import * from ursina.prefabs import * from ursina.prefabs.first_person_controller import * from Math import InverseLefp import Noise app = Ursina() #The maximum height of the terrain maxHeight = 10 #Control the width and height of the map mapWidth = 10 mapHeight = 10 #A class that create a block class Voxel(Button): def __init__(self, position=(0,0,0)): super().__init__( parent = scene, position = position, model = 'cube', origin_y = .5, texture = 'white_cube', color = color.color(0, 0, random.uniform(.9, 1.0)), highlight_color = color.lime, ) #Detect user key input def input(self, key): if self.hovered: if key == 'right mouse down': #Place block if user right click voxel = Voxel(position=self.position + mouse.normal) if key == 'left mouse down': #Break block if user left click destroy(self) if key == 'escape': #Exit the game if user press the esc key app.userExit() #Return perlin noise value between 0 and 1 with x, y position with scale = noiseScale def GeneratedNoiseMap(y: int, x: int, noiseScale: float): #Check if the noise scale was invalid or not if noiseScale <= 0: noiseScale = 0.001 sampleX = x / noiseScale sampleY = y / noiseScale #The Noise.SimplexNoise().noise2 will return the value between -1 and 1 perlinValue = Noise.SimplexNoise().noise2(sampleX, sampleY) #The InverseLefp will make the value scale to between 0 and 1 perlinValue = InverseLefp(-1, 1, perlinValue) return perlinValue for z in range(mapHeight): for x in range(mapWidth): #Calculating the height of the block and round it to integer height = round(GeneratedNoiseMap(z, x, 20) * maxHeight) #Place the block and make it always below the player block = Voxel(position=(x, height - maxHeight - 1, z)) #Set the collider of the block block.collider = 'mesh' #Character movement player = FirstPersonController() #Run the game app.run() All file in same folder. It was working fine but the FPS is very low, so can anyone help?
I'm not able to test this code at the moment but this should serve as a starting point: level_parent = Entity(model=Mesh(vertices=[], uvs=[])) for z in range(mapHeight): for x in range(mapWidth): height = round(GeneratedNoiseMap(z, x, 20) * maxHeight) block = Voxel(position=(x, height - maxHeight - 1, z)) level_parent.model.vertices.extend(block.model.vertices) level_parent.collider = 'mesh' # call this only once after all vertices are set up For texturing, you might have to add the block.uvs from each block to level_parent.model.uvs as well. Alternatively, call level_parent.model.project_uvs() after setting up the vertices.
On my version of ursina engine (5.0.0) only this code: ` level_parent = Entity(model=Mesh(vertices=[], uvs=[])) for z in range(mapHeight): for x in range(mapWidth): height = round(GeneratedNoiseMap(z, x, 20) * maxHeight) block = Voxel(position=(x, height - maxHeight - 1, z)) #level_parent.model.vertices.extend(block.model.vertices) level_parent.combine().vertices.extend(block.combine().vertices) level_parent.collider = 'mesh' ` is working.
Chaotic billiards simulation
I came to ask for some help with maths and programming. What am I trying to do? I'm trying to implement a simulation of a chaotic billiard system, following the algorithm in this excerpt. How am I trying it? Using numpy and matplotlib, I implemented the following code def boundaryFunction(parameter): return 1 + 0.1 * np.cos(parameter) def boundaryDerivative(parameter): return -0.1 * np.sin(parameter) def trajectoryFunction(parameter): aux = np.sin(beta - phi) / np.sin(beta - parameter) return boundaryFunction(phi) * aux def difference(parameter): return trajectoryFunction(parameter) - boundaryFunction(parameter) def integrand(parameter): rr = boundaryFunction(parameter) dd = boundaryDerivative (parameter) return np.sqrt(rr ** 2 + dd ** 2) ##### Main ##### length_vals = np.array([], dtype=np.float64) alpha_vals = np.array([], dtype=np.float64) # nof initial phi angles, alpha angles, and nof collisions for each. n_phi, n_alpha, n_cols, count = 10, 10, 10, 0 # Length of the boundary total_length, err = integrate.quad(integrand, 0, 2 * np.pi) for phi in np.linspace(0, 2 * np.pi, n_phi): for alpha in np.linspace(0, 2 * np.pi, n_alpha): for n in np.arange(1, n_cols): nu = np.arctan(boundaryFunction(phi) / boundaryDerivative(phi)) beta = np.pi + phi + alpha - nu # Determines next impact coordinate. bnds = (0, 2 * np.pi) phi_new = optimize.minimize_scalar(difference, bounds=bnds, method='bounded').x nu_new = np.arctan(boundaryFunction(phi_new) / boundaryDerivative(phi_new)) # Reflection angle with relation to tangent. alpha_new = phi_new - phi + nu - nu_new - alpha # Arc length for current phi value. arc_length, err = integrate.quad(integrand, 0, phi_new) # Append values to list length_vals = np.append(length_vals, arc_length / total_length) alpha_vals = np.append(alpha_vals, alpha) count += 1 print "{}%" .format(100 * count / (n_phi * n_alpha)) What is the problem? When calculating phi_new, the equation has two solutions (assuming the boundary is convex, which is.) I must enforce that phi_new is the solution which is different from phi, but I don't know how to do that. Are there more issues with the code? What should the output be? A phase space diagram of S x Alpha, looking like this. Any help is very appreciated! Thanks in advance.
One way you could try would be (given there really are only two solutions) would be epsilon = 1e-7 # tune this delta = 1e-4 # tune this # ... bnds = (0, 2 * np.pi) phi_new = optimize.minimize_scalar(difference, bounds=bnds, method='bounded').x if abs(phi_new - phi) < epsilon: bnds_1 = (0, phi - delta) phi_new_1 = optimize.minimize_scalar(difference, bounds=bnds_1, method='bounded').x bnds_2 = (phi + delta, 2 * np.pi) phi_new_2 = optimize.minimize_scalar(difference, bounds=bnds_2, method='bounded').x if difference(phi_new_1) < difference(phi_new_2): phi_new = phi_new_1 else: phi_new = phi_new_2 Alternatively, you could introduce a penalty-term, e.g. delta*exp(eps/(x-phi)^2) with appropriate choices of epsilon and delta.
fmin_slsqp returns different solutions to the same system
The following is as much I could boil it down. I'm trying to solve a system of equations with 18 equations and 18 variables. For the moment, I hold 4 of these variables fixed. Originally, I got weird results. So I simplified the problem so far such that the first 9 and the last 9 equations are separate and identical. Moreover, the problem is exactly identified: There should be one unique solution. The solution vector contains 14 elements (18 minus the 4 fixed variables). Since these are ordered properly, the first 7 solution variables should be identical to the last 7 solution variables. However, they are not. I checked identity of equations by putting in an identical vector x[:7] = x[7:] and checking that res[:9] == res[9:] were all true. Following is the output that I get: Optimization terminated successfully. (Exit mode 0) Current function value: 0.125393271845 Iterations: 18 Function evaluations: 297 Gradient evaluations: 18 Out[223]: J W w v U u Y 0 0.663134 0.237578 0.251245 10.00126 0.165647 0.093939 0.906657 1 0.022635 0.825547 1.000000 10.00340 0.512898 0.089790 0.909918 Where I have stacked the first 7 variables into the first row and the next 7 variables into the second row. Clearly, these are not identical. Code for reproduction follows import numpy as np # parameters class Parameters(object): r = 1.03 sBar = 0.1 sB = 0.1 c = 0.1 z = 0.001 H = 1 epsilon = 1 beta = 0.1 def q(theta): if theta <= 0: return 999 return float(1)/theta def f(theta): if theta < 1: return 0 return 1 - float(1)/theta # sum_all allows to see residual as vector, not summed def twoSectorFake(x, Param, sum_all=True): JBar, WBar, wBar, vBar, UBar, uBar, YBar = x[:7] JB, WB, wB, vB, UB, uB, YB = x[7:] VBar = 0 VB = 0 pB = 1 pBar = 1 #theta = float(vB + vBar)/u thetaBar = float(vBar)/uBar thetaB = float(vB)/uB res = np.empty(18,) res[0] = Param.r*JBar - (pBar - wBar - Param.sBar*(JBar - VBar) ) res[1] = Param.r * VBar - ( -Param.c + q(thetaBar) * (JBar - VBar) ) res[2] = Param.r * WBar - (wBar - Param.sBar * (WBar - UBar) ) res[3] = Param.r * UBar - (Param.z + f(thetaBar) * (WBar - UBar) ) res[4] = Param.sBar * YBar - vBar * q(thetaBar) res[5] = Param.sBar * YBar - uBar * f(thetaBar) res[6] = JBar - (1 - Param.beta) * (JBar + WBar - UBar) res[7] = Param.H - YBar - uBar res[8] = thetaBar * uBar - vBar res[9] = Param.r*JB - (pB - wB - Param.sB*(JB - VB)) res[10] = Param.r*VB - ( -Param.c + q(thetaB) * (JB - VB)) res[11] = Param.r * WB - (wB - Param.sB * (WB - UB)) res[12] = Param.r * UB - (Param.z + f(thetaB) * (WB - UB)) res[13] = Param.sB * YB - vB*q(thetaB) res[14] = Param.sB * YB - uB * f(thetaB) res[15] = JB - (1 - Param.beta) * (JB + WB - UB) res[16] = Param.H - YB - uB res[17] = thetaB * uB - vB idx = abs(res > 10000) # don't square too big numbers, they may become INF and the problem won't solve res[idx] = abs(res[idx]) res[~idx] = res[~idx]**2 if (sum_all==False): return res return sum(res) Param = Parameters() x2 = np.empty(0,) boundaries2 = [] # JBar x2 = np.append(x2, 1) boundaries2.append([0, 100]) # WBar x2 = np.append(x2, 1) boundaries2.append([0, 100]) # wBar x2 = np.append(x2, 0.5) boundaries2.append([0.01, 100]) # vBar x2 = np.append(x2, 10) boundaries2.append([0.01, 100000]) # UBar x2 = np.append(x2, float(Param.z)/(Param.r-1)+1) boundaries2.append([float(Param.z)/(Param.r-1) - 0.1, 100]) # uBar x2 = np.append(x2, 0.5*Param.H) boundaries2.append([0.0000001, Param.H]) # YBar x2 = np.append(x2, 0.5*Param.H) boundaries2.append([0.0001, Param.H]) # JB x2 = np.append(x2, 1) boundaries2.append([0, 100]) # WB x2 = np.append(x2, 1) boundaries2.append([0, 100]) # wB x2 = np.append(x2, 0.5) boundaries2.append([1, 100]) # vB x2 = np.append(x2, 10) boundaries2.append([0.01, 100]) # UB x2 = np.append(x2, float(Param.z)/(Param.r-1)+1) boundaries2.append([float(Param.z)/(Param.r-1) - 0.1, 100]) # uB x2 = np.append(x2, 0.5*Param.H) boundaries2.append([0.0000001, Param.H]) # YB x2 = np.append(x2, 0.5*Param.H) boundaries2.append([0.0001, Param.H]) result = optimize.fmin_slsqp(func=twoSectorFake, x0=x2, bounds=boundaries2, args=(Param,), iter=200) res1 = result[:7] res2 = result[7:] df = pd.DataFrame(np.reshape(res1, (1,7)), columns=['J', 'W', 'w', 'v', 'U', 'u','Y']) df.loc[1] = np.reshape(res2, (1,7)) print df
EDIT: your variable boundaries2 isn't symmetric, i.e. boundaries2[7:]!=boundaries2[:7] . Try writing boundaries2 = boundaries2[7:]*2 just before your call to fmin_slsqp and you get a symmetric local minimum. I leave the previous general comments on your setup below, because they apply in any case. First of all, are you sure that there exists only one solution to your problem? if not, I wouldn't expect necessarily the scipy numerical routine to return the solution you have in mind. It can converge to any other non-symmetric solution. In second instance, you are not solving the system of equations. If you evaluate twoSectorFake(result,Param) at the end of your code, you get 0.15. You may be better off with other root solvers, see the root finding section. This means that you're then looking at a local minimum of your target function, i.e. not a zero. Again, there's no reason why the numerical routine should necessarily calculate a symmetric local minimum.
Simplex Noise Function: Unexpected Results
I'm trying to adapt this noise module to a project I'm working on but I'm not getting the results I was expecting: https://pypi.python.org/pypi/noise/ Instead of a varied height-map, each row tends to have the exact same value. If I create something 250x250 it will generate the same value 250 times and then generate a new value 250 times until it ends. Here is the function I'm currently using. I understand this function fairly well but I'm just not sure how to get more "interesting" results. Thank you for your help. class SimplexNoise(BaseNoise): def noise2(self, x, y): """2D Perlin simplex noise. Return a floating point value from -1 to 1 for the given x, y coordinate. The same value is always returned for a given x, y pair unless the permutation table changes (see randomize above). """ # Skew input space to determine which simplex (triangle) we are in s = (x + y) * _F2 i = floor(x + s) j = floor(y + s) t = (i + j) * _G2 x0 = x - (i - t) # "Unskewed" distances from cell origin y0 = y - (j - t) if x0 > y0: i1 = 1; j1 = 0 # Lower triangle, XY order: (0,0)->(1,0)->(1,1) else: i1 = 0; j1 = 1 # Upper triangle, YX order: (0,0)->(0,1)->(1,1) x1 = x0 - i1 + _G2 # Offsets for middle corner in (x,y) unskewed coords y1 = y0 - j1 + _G2 x2 = x0 + _G2 * 2.0 - 1.0 # Offsets for last corner in (x,y) unskewed coords y2 = y0 + _G2 * 2.0 - 1.0 # Determine hashed gradient indices of the three simplex corners perm = BaseNoise.permutation ii = int(i) % BaseNoise.period jj = int(j) % BaseNoise.period gi0 = perm[ii + perm[jj]] % 12 gi1 = perm[ii + i1 + perm[jj + j1]] % 12 gi2 = perm[ii + 1 + perm[jj + 1]] % 12 # Calculate the contribution from the three corners tt = 0.5 - x0**2 - y0**2 if tt > 0: g = _GRAD3[gi0] noise = tt**4 * (g[0] * x0 + g[1] * y0) else: noise = 0.0 tt = 0.5 - x1**2 - y1**2 if tt > 0: g = _GRAD3[gi1] noise += tt**4 * (g[0] * x1 + g[1] * y1) tt = 0.5 - x2**2 - y2**2 if tt > 0: g = _GRAD3[gi2] noise += tt**4 * (g[0] * x2 + g[1] * y2) return noise * 70.0 # scale noise to [-1, 1] win = pygcurse.PygcurseWindow(85, 70, 'Generate') octaves = 2 ysize = 150 xsize = 150 freq = 32.0 * octaves for y in range(ysize): for x in range(xsize): tile = SimplexNoise.noise2(x / freq, y / freq, octaves) win.write(str(tile) + "\n")