Related
I have a class called "Edit"
function Edit:new(x,y,w,h,text,fnt)
o = {}
setmetatable(o,EditMt)
self.__index = self
self.x = x or 0
self.y = y or 0
self.width = w or 10
self.height = h or 10
self.text = text or ""
self.active = false
self.font = fnt or font
self.yo = -(self.height - self.font:getHeight()) / 2
return o
end
and that class has a function called draw(made with Löve2d)
function Edit:draw( )
if self.active then
love.graphics.setColor(255,255,255,255)
love.graphics.rectangle("fill",self.x,self.y,self.width,self.height)
love.graphics.setColor(0,0,0,255)
love.graphics.printf(self.text,self.font,self.x,self.y,self.width, "center",0,1,1,0,self.yo)
else
love.graphics.setColor(255,255,255,255)
love.graphics.rectangle("line",self.x,self.y,self.width,self.height)
love.graphics.printf(self.text,self.font,self.x,self.y,self.width, "center",0,1,1,0,self.yo)
end
end
and in my main i create 2 of them
edit1 = Edit:new(10,10,60,50,"1")
edit2 = Edit:new(80,10,60,50,"2")
and draw them in the callback
function love.draw( )
edit1:draw()
edit2:draw()
end
but it only draws edit2? if i switch the places in draw it still only draws edit2 but if i switch their places while creating them in the main it now only draws edit1?
This is the most common beginners mistake when they get into OOP in Lua.
You're assigning all those values to self which is Edit. But if you want to change your instance you need to assign them to o.
Otherwise each call to Edit.new will overwrite the values.
The second problem is that your instance o is a global. You need it to be local! Or you will overwrite your instances each time.
function Edit:new (x,y,w,h,text,fnt)
local o = {}
setmetatable(o, self)
self.__index = self
o.x = x or 0
o.y = y or 0
-- and so forth
return o
end
Read this:
https://www.lua.org/pil/16.html
http://lua-users.org/wiki/ObjectOrientedProgramming
You initiates your object not quite correct.
In new function you initiates your object and self in this function is your metatatable.
The other problem that you creates global object o.
So your new function must be:
function Edit:new(x,y,w,h,text,fnt)
local o = {}
setmetatable(o, self)
self.__index = self
o.x = x or 0
o.y = y or 0
o.width = w or 10
o.height = h or 10
o.text = text or ""
o.active = false
o.font = fnt or font
o.yo = -(o.height - o.font:getHeight()) / 2
return o
end
I have created collision for the player and enemies (the collision isn't perfect but works for the most part) in my game but am having a hard time figuring out how to create a death animation for the player.
I want the player's ship to explode when the enemies hit you, how would I go about this?
Here is my player file:
Player = Class{}
function Player:init(x, y, width, height)
self.player = {}
self.x = x
self.y = y
self.height = height
self.dx = 0
self.image = love.graphics.newImage('images/player.png')
self.width = self.image:getWidth()
self.fire_sound = love.audio.newSource('sounds/laser.wav', 'static')
self.fire_sound:setVolume(.25)
self.player_explosion = love.audio.newSource('sounds/player_explosion.wav', 'static')
self.player_explosion:setVolume(25)
self.cooldown = 10
self.bullets = {}
end
function Player:update(dt)
self.x = self.x + self.dx * dt
if self.x <= 0 then
self.dx = 0
self.x = 0
end
if self.x >= WINDOW_WIDTH - self.width * 4 then
self.dx = 0
self.x = WINDOW_WIDTH - self.width * 4
end
end
function Player:fire()
if self.cooldown <= 0 then
love.audio.play(player.fire_sound)
if BULLET_COUNTER >= 1 then
love.audio.stop(player.fire_sound)
love.audio.play(player.fire_sound)
self.cooldown = 30
bullet = {}
bullet.x = player.x + 25
bullet.y = player.y + 5
table.insert(self.bullets, bullet)
BULLET_COUNTER = 0
return
end
self.cooldown = 10
bullet = {}
bullet.x = self.x + 25
bullet.y = self.y + 5
table.insert(self.bullets, bullet)
BULLET_COUNTER = BULLET_COUNTER + 1
end
end
function Player:render()
love.graphics.setColor(255, 255, 255)
love.graphics.draw(self.image, self.x, self.y, 0, 4)
end
function Player:checkCollision(enemies)
for i,e in ipairs(enemies) do
if e.y + e.height >= self.y and e.y <= self.y + self.height and e.x <= self.x + self.width and e.x + e.width >= self.x + self.width then
love.audio.stop(self.player_explosion)
love.audio.play(self.player_explosion)
table.remove(enemies, i)
LIVES = LIVES - 1
end
end
end
Here is my main file if you need it:
Class = require 'class'
require 'Player'
GAME_STATE = 'start'
WINDOW_WIDTH = 720
WINDOW_HEIGHT = 900
love.window.setMode(WINDOW_WIDTH, WINDOW_HEIGHT)
SCORE = 0
LIVES = 3
PLAYER_SPEED = 300
-- map variables
map = {}
map.image = love.graphics.newImage('images/background_final.png')
map.width = 720
map.height = 900
map.music = love.audio.newSource('sounds/Battle-in-the-Stars.wav', 'static')
-- enemy variables
enemy = {}
enemies_controller = {}
enemies_controller.enemies = {}
alienImage = love.graphics.newImage('images/alien2.png')
alienship1_Image = love.graphics.newImage('images/enemyship1.png')
alienship2_Image = love.graphics.newImage('images/enemyship4.png')
enemies_controller.explosion = love.audio.newSource('sounds/explosion.wav', 'static')
enemies_controller.explosion:setVolume(.25)
spawnTimer = 0
spawnTimer_Max = 0.75
SMALL_WIDTH = 70
SMALL_HEIGHT = 70
-- star variables for warp effect
star = {}
stars_controller = {}
stars_controller.stars = {}
starSpawnTimer = 0
starSpawnTimer_Max = 0.25
STAR_WIDTH = 100
STAR_HEIGHT = 100
BULLET_COUNTER = 0
-- this function allows us to scale an image we created to a desired height and width
function getImageScaleForNewDimensions(image, newWidth, newHeight)
local currentWidth, currentHeight = image:getDimensions()
return ( newWidth / currentWidth ), ( newHeight / currentHeight )
end
-- check collisions for enemies and bullets
function checkCollisions(enemies, bullets)
for i,e in ipairs(enemies) do
for j,b in ipairs(bullets) do
-- checks if the hitboxes for the bullet and the enemy collide
-- if they do remove the enemy and the bullet that collided
if b.y <= e.y + e.height and b.x > e.x and b.x < e.x + e.width then
love.audio.stop(enemies_controller.explosion)
table.remove(enemies, i)
table.remove(bullets, j)
love.audio.play(enemies_controller.explosion)
SCORE = SCORE + 10
end
end
end
end
function love.load()
love.graphics.setDefaultFilter('nearest', 'nearest')
love.window.setTitle('Space Attack')
title_largeFont = love.graphics.newFont('fonts/Mario-Kart-DS.ttf', 40)
title_smallFont = love.graphics.newFont('fonts/Mario-Kart-DS.ttf', 20)
largeFont = love.graphics.newFont('fonts/04B_30__.TTF', 32)
smallFont = love.graphics.newFont('fonts/04B_30__.TTF', 20)
love.graphics.setFont(largeFont)
player = Player(WINDOW_WIDTH / 2 - 40, WINDOW_HEIGHT - 100, 10, 10)
map.music:setLooping(true)
map.music:setVolume(.25)
map.music:play()
end
function enemies_controller:spawnEnemy(x, y, n)
enemy = {}
enemy.x = x
enemy.y = y
enemy.width = SMALL_WIDTH
enemy.height = SMALL_HEIGHT
enemy.bullets = {}
enemy.cooldown = 10
-- n is a random variable that determines what type of enemy spawns
if n == 0 then
enemy.image = alienImage
enemy.speed = 5
elseif n == 1 then
enemy.image = alienship1_Image
enemy.speed = 6
else
enemy.image = alienship2_Image
enemy.speed = 7
end
table.insert(self.enemies, enemy)
end
function stars_controller:spawnStars(x, y)
star = {}
star.x = x
star.y = y
star.speed = 10
star.image = love.graphics.newImage('images/star.png')
star.width = SMALL_WIDTH
star.height = SMALL_HEIGHT
table.insert(self.stars, star)
end
function love.update(dt)
player.cooldown = player.cooldown - 1
checkCollisions(enemies_controller.enemies, player.bullets)
player:checkCollision(enemies_controller.enemies)
-- checks spawn timer, if > 0 don't spawn an enemy but if it is spawn an enemy
if spawnTimer > 0 then
spawnTimer = spawnTimer - dt
else
if GAME_STATE == 'play' then
enemies_controller:spawnEnemy(love.math.random(0, WINDOW_WIDTH - SMALL_WIDTH), 0, love.math.random(0,2))
spawnTimer = spawnTimer_Max
end
end
-- same situation as spawn timer for enemies, but this is for the warp effect
if starSpawnTimer > 0 then
starSpawnTimer = starSpawnTimer - dt
else
stars_controller:spawnStars(love.math.random(0, WINDOW_WIDTH - SMALL_WIDTH), 0)
starSpawnTimer = starSpawnTimer_Max
end
-- checking user input to move left and right
if love.keyboard.isDown('right') then
if GAME_STATE == 'play' then
player.dx = PLAYER_SPEED
end
elseif love.keyboard.isDown('left') then
if GAME_STATE == 'play' then
player.dx = -PLAYER_SPEED
end
else
player.dx = 0
end
-- checking user input for firing function
if love.keyboard.isDown('space') then
if GAME_STATE == 'play' then
player:fire()
end
end
-- this removes enemies if they are too far off the scree
-- also how the enemies move downards
-- NEED TO ADD MOVEMENT FUNCTIONS HERE FOR DIFFERENT ENEMIES
for i,e in ipairs(enemies_controller.enemies) do
e.y = e.y + e.speed
if e.y > WINDOW_HEIGHT then
table.remove(enemies_controller.enemies, i)
end
end
-- removes bullets if they travel too far off the screen
-- this also moves the bullets upwards
for i,v in ipairs(player.bullets) do
if v.y < 0 then
table.remove(player.bullets, i)
end
v.y = v.y - 8
end
-- removes stars if they travel too far off screen
-- moves the stars to create warp effect
for i,s in ipairs(stars_controller.stars) do
s.y = s.y + s.speed
if s.y > WINDOW_HEIGHT then
table.remove(stars_controller.stars, i)
end
end
-- checks lives to determine game state
if LIVES == 0 then
GAME_STATE = 'end'
end
player:update(dt)
end
-- key pressed function so we can exit the game and start the game
function love.keypressed(key)
if key == 'escape' then
love.event.quit()
elseif key == 'enter' or key == 'return' then
if GAME_STATE == 'start' then
GAME_STATE = 'play'
end
end
end
function love.draw()
-- checks gamestate and if it is
if GAME_STATE == 'start' then
-- draw the warp effect
for _,s in pairs(stars_controller.stars) do
local scaleX, scaleY = getImageScaleForNewDimensions(s.image, STAR_WIDTH, STAR_HEIGHT)
love.graphics.draw(s.image, s.x, s.y, 0, 2, 4)
end
-- draw the player
player:render()
love.graphics.setColor(200, 0, 200, 255)
love.graphics.setFont(title_largeFont)
love.graphics.print('WELCOME TO SPACE ATTACK!', WINDOW_WIDTH / 2 - 290, WINDOW_HEIGHT / 2)
love.graphics.setFont(title_smallFont)
love.graphics.print('press ENTER to begin!', WINDOW_WIDTH / 2 - 110, WINDOW_HEIGHT / 2 + 100)
end
if GAME_STATE == 'play' then
-- draw the map
love.graphics.setColor(255, 255, 255)
local map_width, map_height = getImageScaleForNewDimensions(map.image, map.width, map.height)
love.graphics.draw(map.image, 0, 0, 0, map_width, map_height)
-- draw the enemies
for _,e in pairs(enemies_controller.enemies) do
local scaleX, scaleY = getImageScaleForNewDimensions(e.image, SMALL_WIDTH, SMALL_HEIGHT)
love.graphics.draw(e.image, e.x, e.y, 0, scaleX, scaleY)
end
-- draw the warp effect
for _,s in pairs(stars_controller.stars) do
love.graphics.draw(s.image, s.x, s.y, 0, 1, 4)
end
-- draw the player
player:render()
-- draw the bullets
love.graphics.setColor(255, 255, 255)
for _,v in pairs(player.bullets) do
love.graphics.rectangle('fill', v.x, v.y, 10, 10)
end
displayScore()
displayLives()
end
if GAME_STATE == 'end' then
love.audio.stop()
love.graphics.setColor(200, 0, 200, 255)
love.graphics.setFont(title_largeFont)
love.graphics.print('GAME OVER!', WINDOW_WIDTH / 2 - 120, WINDOW_HEIGHT / 2)
love.graphics.setFont(title_smallFont)
love.graphics.print('score ' .. tostring(SCORE), WINDOW_WIDTH / 2 - 60, WINDOW_HEIGHT / 2 + 50)
end
end
function displayScore()
if GAME_STATE == 'play' then
love.graphics.setColor(0, 255, 0, 255)
love.graphics.setFont(largeFont)
love.graphics.print('Score: ' .. tostring(SCORE), WINDOW_WIDTH / 2 - 130, 10)
end
end
function displayLives()
if GAME_STATE == 'play' then
love.graphics.setColor(255, 0, 0, 255)
love.graphics.setFont(smallFont)
love.graphics.print('Lives: ' .. tostring(LIVES), WINDOW_WIDTH - 150, 10)
end
end
I want the player's ship to explode when the enemies hit you, how would I go about this?
I assume you are asking about creating the actual visual effect of an explosion. LÖVE's particle system has all the functionality to create that sort of animation / effect, but can be a bit overkill if you are just starting out.
A simple alternative would be to remove the player's ship and replace it with an animated sprite of an explosion. You could use a library to handle the animation code for you, or just use it as a reference point for your own animation code.
An animation usually consists of multiple frames or images which are displayed in a sequence. E.g. a very simple animation could look like this:
Frame: Small Explosion
Frame: Explosion gets bigger
Frame: Explosion gets smaller again
Frame: Smoke appears
Frame: Smoke vanishes and animation is finished
Each of these frames would be contained in one big image or spritesheet.
In LÖVE you will have to load the spritesheet and divide it into its frames by using quads:
local spritesheet = love.graphics.newImage("animation.png")
-- Create a quad for each frame in the spritesheet.
-- Here we assume that each frame is a 16x16 square inside of the spritesheet.
local animation = {
love.graphics.newQuad(0, 0, 16, 16, spritesheet:getDimensions()),
love.graphics.newQuad(16, 0, 16, 16, spritesheet:getDimensions()),
-- more frames
}
-- To display the animation we draw one quad each frame and then update the index variable.
-- Of course in a real game you'd add a delay between each frame and check for the boundaries
-- of the array and so on.
local i = 1
function love.draw()
love.graphics.draw(spritesheet, animation[i], 50, 50)
i = i + 1
end
This is not a perfect example, but I hope it shows the general idea of how animations can work.
I implemented the LSDD changepoint detection method decribed in [1] in Julia, to see if I could make it faster than the existing python implementation [2], which is based on a grid search that looks for the optimal parameters.
I obtain the desired results but despite my best efforts, my grid search version of it takes about the same time to compute as the python one, which is still way too long for real applications.
I also tried using the Optimize package which only makes things worse (2 or 3 times slower).
Here is the grid search that I implemented :
using Random
using LinearAlgebra
function squared_distance(X::Array{Float64,1},C::Array{Float64,1})
sqd = zeros(length(X),length(C))
for i in 1:length(X)
for j in 1:length(C)
sqd[i,j] = X[i]^2 + C[j]^2 - 2*X[i]*C[j]
end
end
return sqd
end
function lsdd(x::Array{Float64,1},y::Array{Float64,1}; folds = 5, sigma_list = nothing , lambda_list = nothing)
lx,ly = length(x), length(y)
b = min(lx+ly,300)
C = shuffle(vcat(x,y))[1:b]
CC_dist2 = squared_distance(C,C)
xC_dist2, yC_dist2 = squared_distance(x,C), squared_distance(y,C)
Tx,Ty = length(x) - div(lx,folds), length(y) - div(ly,folds)
#Define the training and testing data sets
cv_split1, cv_split2 = floor.(collect(1:lx)*folds/lx), floor.(collect(1:ly)*folds/ly)
cv_index1, cv_index2 = shuffle(cv_split1), shuffle(cv_split2)
tr_idx1,tr_idx2 = [findall(x->x!=i,cv_index1) for i in 1:folds], [findall(x->x!=i,cv_index2) for i in 1:folds]
te_idx1,te_idx2 = [findall(x->x==i,cv_index1) for i in 1:folds], [findall(x->x==i,cv_index2) for i in 1:folds]
xTr_dist, yTr_dist = [xC_dist2[i,:] for i in tr_idx1], [yC_dist2[i,:] for i in tr_idx2]
xTe_dist, yTe_dist = [xC_dist2[i,:] for i in te_idx1], [yC_dist2[i,:] for i in te_idx2]
if sigma_list == nothing
sigma_list = [0.25, 0.5, 0.75, 1, 1.2, 1.5, 2, 2.5, 2.2, 3, 5]
end
if lambda_list == nothing
lambda_list = [1.00000000e-03, 3.16227766e-03, 1.00000000e-02, 3.16227766e-02,
1.00000000e-01, 3.16227766e-01, 1.00000000e+00, 3.16227766e+00,
1.00000000e+01]
end
#memory prealocation
score_cv = zeros(length(sigma_list),length(lambda_list))
H = zeros(b,b)
hx_tr, hy_tr = [zeros(b,1) for i in 1:folds], [zeros(b,1) for i in 1:folds]
hx_te, hy_te = [zeros(1,b) for i in 1:folds], [zeros(1,b) for i in 1:folds]
#h_tr,h_te = zeros(b,1), zeros(1,b)
theta = zeros(b)
for (sigma_idx,sigma) in enumerate(sigma_list)
#the expression of H is different for higher dimension
#H = sqrt((sigma^2)*pi)*exp.(-CC_dist2/(4*sigma^2))
set_H(H,CC_dist2,sigma,b)
#check if the sum is performed along the right dimension
set_htr(hx_tr,xTr_dist,sigma,Tx), set_htr(hy_tr,yTr_dist,sigma,Ty)
set_hte(hx_te,xTe_dist,sigma,lx-Tx), set_hte(hy_te,yTe_dist,sigma,ly-Ty)
for i in 1:folds
h_tr = hx_tr[i] - hy_tr[i]
h_te = hx_te[i] - hy_te[i]
#set_h(h_tr,hx_tr[i],hy_tr[i],b)
#set_h(h_te,hx_te[i],hy_te[i],b)
for (lambda_idx,lambda) in enumerate(lambda_list)
set_theta(theta,H,lambda,h_tr,b)
score_cv[sigma_idx,lambda_idx] += dot(theta,H*theta) - 2*dot(theta,h_te)
end
end
end
#retrieve the value of the optimal parameters
sigma_chosen = sigma_list[findmin(score_cv)[2][2]]
lambda_chosen = lambda_list[findmin(score_cv)[2][2]]
#calculating the new "optimal" solution
H = sqrt((sigma_chosen^2)*pi)*exp.(-CC_dist2/(4*sigma_chosen^2))
H_lambda = H + lambda_chosen*Matrix{Float64}(I, b, b)
h = (1/lx)*sum(exp.(-xC_dist2/(2*sigma_chosen^2)),dims = 1) - (1/ly)*sum(exp.(-yC_dist2/(2*sigma_chosen^2)),dims = 1)
theta_final = H_lambda\transpose(h)
f = transpose(theta_final).*sum(exp.(-vcat(xC_dist2,yC_dist2)/(2*sigma_chosen^2)),dims = 1)
L2 = 2*dot(theta_final,h) - dot(theta_final,H*theta_final)
return L2
end
function set_H(H::Array{Float64,2},dist::Array{Float64,2},sigma::Float64,b::Int16)
for i in 1:b
for j in 1:b
H[i,j] = sqrt((sigma^2)*pi)*exp(-dist[i,j]/(4*sigma^2))
end
end
end
function set_theta(theta::Array{Float64,1},H::Array{Float64,2},lambda::Float64,h::Array{Float64,2},b::Int64)
Hl = (H + lambda*Matrix{Float64}(I, b, b))
LAPACK.posv!('L', Hl, h)
theta = h
end
function set_htr(h::Array{Float64,1},dists::Array{Float64,2},sigma::Float64,T::Int16)
for (CVidx,dist) in enumerate(dists)
for (idx,value) in enumerate((1/T)*sum(exp.(-dist/(2*sigma^2)),dims = 1))
h[CVidx][idx] = value
end
end
end
function set_hte(h::Array{Float64,1},dists::Array{Float64,2},sigma::Array{Float64,1},T::Int16)
for (CVidx,dist) in enumerate(dists)
for (idx,value) in enumerate((1/T)*sum(exp.(-dist/(2*sigma^2)),dims = 1))
h[CVidx][idx] = value
end
end
end
function set_h(h,h1,h2,b)
for i in 1:b
h[i] = h1[i] - h2[i]
end
end
The set_H, set_h and set_theta functions are there because I read somewhere that modifying prealocated memory in place with a function was faster, but it did not make a great difference.
To test it, I use two random distribution as input data :
x,y = rand(500),1.5*rand(500)
lsdd(x,y) #returns a value around 0.3
Now here is the version of the code where I try to use Optimizer :
function Theta(sigma::Float64,lambda::Float64,x::Array{Float64,1},y::Array{Float64,1},folds::Int8)
lx,ly = length(x), length(y)
b = min(lx+ly,300)
C = shuffle(vcat(x,y))[1:b]
CC_dist2 = squared_distance(C,C)
xC_dist2, yC_dist2 = squared_distance(x,C), squared_distance(y,C)
#the subsets are not be mutually exclusive !
Tx,Ty = length(x) - div(lx,folds), length(y) - div(ly,folds)
shuffled_x, shuffled_y = [shuffle(1:lx) for i in 1:folds], [shuffle(1:ly) for i in 1:folds]
cv_index1, cv_index2 = floor.(collect(1:lx)*folds/lx)[shuffle(1:lx)], floor.(collect(1:ly)*folds/ly)[shuffle(1:ly)]
tr_idx1,tr_idx2 = [i[1:Tx] for i in shuffled_x], [i[1:Ty] for i in shuffled_y]
te_idx1,te_idx2 = [i[Tx:end] for i in shuffled_x], [i[Ty:end] for i in shuffled_y]
xTr_dist, yTr_dist = [xC_dist2[i,:] for i in tr_idx1], [yC_dist2[i,:] for i in tr_idx2]
xTe_dist, yTe_dist = [xC_dist2[i,:] for i in te_idx1], [yC_dist2[i,:] for i in te_idx2]
score_cv = 0
Id = Matrix{Float64}(I, b, b)
H = sqrt((sigma^2)*pi)*exp.(-CC_dist2/(4*sigma^2))
hx_tr, hy_tr = [transpose((1/Tx)*sum(exp.(-dist/(2*sigma^2)),dims = 1)) for dist in xTr_dist], [transpose((1/Ty)*sum(exp.(-dist/(2*sigma^2)),dims = 1)) for dist in yTr_dist]
hx_te, hy_te = [(lx-Tx)*sum(exp.(-dist/(2*sigma^2)),dims = 1) for dist in xTe_dist], [(ly-Ty)*sum(exp.(-dist/(2*sigma^2)),dims = 1) for dist in yTe_dist]
for i in 1:folds
h_tr, h_te = hx_tr[i] - hy_tr[i], hx_te[i] - hy_te[i]
#theta = (H + lambda * Id)\h_tr
theta = copy(h_tr)
Hl = (H + lambda*Matrix{Float64}(I, b, b))
LAPACK.posv!('L', Hl, theta)
score_cv += dot(theta,H*theta) - 2*dot(theta,h_te)
end
return score_cv,(CC_dist2,xC_dist2,yC_dist2)
end
function cost(params::Array{Float64,1},x::Array{Float64,1},y::Array{Float64,1},folds::Int8)
s,l = params[1],params[2]
return Theta(s,l,x,y,folds)[1]
end
"""
Performs the optinization
"""
function lsdd3(x::Array{Float64,1},y::Array{Float64,1}; folds = 4)
start = [1,0.1]
b = min(length(x)+length(y),300)
lx,ly = length(x),length(y)
#result = optimize(params -> cost(params,x,y,folds),fill(0.0,2),fill(50.0,2),start, Fminbox(LBFGS(linesearch=LineSearches.BackTracking())); autodiff = :forward)
result = optimize(params -> cost(params,x,y,folds),start, BFGS(),Optim.Options(f_calls_limit = 5, iterations = 5))
#bboptimize(rosenbrock2d; SearchRange = [(-5.0, 5.0), (-2.0, 2.0)])
#result = optimize(cost,[0,0],[Inf,Inf],start, Fminbox(AcceleratedGradientDescent()))
sigma_chosen,lambda_chosen = Optim.minimizer(result)
CC_dist2, xC_dist2, yC_dist2 = Theta(sigma_chosen,lambda_chosen,x,y,folds)[2]
H = sqrt((sigma_chosen^2)*pi)*exp.(-CC_dist2/(4*sigma_chosen^2))
h = (1/lx)*sum(exp.(-xC_dist2/(2*sigma_chosen^2)),dims = 1) - (1/ly)*sum(exp.(-yC_dist2/(2*sigma_chosen^2)),dims = 1)
theta_final = (H + lambda_chosen*Matrix{Float64}(I, b, b))\transpose(h)
f = transpose(theta_final).*sum(exp.(-vcat(xC_dist2,yC_dist2)/(2*sigma_chosen^2)),dims = 1)
L2 = 2*dot(theta_final,h) - dot(theta_final,H*theta_final)
return L2
end
No matter, which kind of option I use in the optimizer, I always end up with something too slow. Maybe the grid search is the best option, but I don't know how to make it faster... Does anyone have an idea how I could proceed further ?
[1] : http://www.mcduplessis.com/wp-content/uploads/2016/05/Journal-IEICE-2014-CLSDD-1.pdf
[2] : http://www.ms.k.u-tokyo.ac.jp/software.html
I've discretised a diffusion equation with FEniCS as follows:
def DiscretiseEquation(h):
mesh = UnitSquareMesh(h, h)
V = FunctionSpace(mesh, 'Lagrange', 1)
def on_boundary(x, on_boundary):
return on_boundary
bc_value = Constant(0.0)
boundary_condition = DirichletBC(V, bc_value, on_boundary)
class RandomDiffusionField(Expression):
def __init__(self, m, n, element):
self._rand_field = np.exp(-np.random.randn(m, n))
self._m = m
self._n = n
self._ufl_element = element
def eval(self, value, x):
x_index = np.int(np.floor(self._m * x[0]))
y_index = np.int(np.floor(self._n * x[1]))
i = min(x_index, self._m - 1)
j = min(y_index, self._n - 1)
value[0] = self._rand_field[i, j]
def value_shape(self):
return(1, )
class RandomRhs(Expression):
def __init__(self, m, n, element):
self._rand_field = np.random.randn(m, n)
self._m = m
self._n = n
self._ufl_element = element
def eval(self, value, x):
x_index = np.int(np.floor(self._m * x[0]))
y_index = np.int(np.floor(self._n * x[1]))
i = min(x_index, self._m - 1)
j = min(y_index, self._n - 1)
value[0] = self._rand_field[i, j]
def value_shape(self):
return (1, )
u = TrialFunction(V)
v = TestFunction(V)
random_field = RandomDiffusionField(100, 100, element=V.ufl_element())
zero = Expression("0", element=V.ufl_element())
one = Expression("1", element=V.ufl_element())
diffusion = as_matrix(((random_field, zero), (zero, one)))
a = inner(diffusion * grad(u), grad(v)) * dx
L = RandomRhs(h, h, element=V.ufl_element()) * v * dx
A = assemble(a)
b = assemble(L)
boundary_condition.apply(A, b)
A = as_backend_type(A).mat()
(indptr, indices, data) = A.getValuesCSR()
mat = csr_matrix((data, indices, indptr), shape=A.size)
rhs = b.array()
#Solving
x = spsolve(mat, rhs)
#Conversion to a FEniCS function
u = Function(V)
u.vector()[:] = x
I am running the GMRES solver as normal. The callback argument is a separate iteration counter I've defined.
DiscretiseEquation(100)
A = mat
b = rhs
x, info = gmres(A, b, callback = IterCount())
The routine returns a NameError, stating that 'mat' is not defined:
NameError Traceback (most recent call last)
<ipython-input-18-e096b2eea097> in <module>()
1 DiscretiseEquation(200)
----> 2 A = mat
3 b = rhs
4 x_200, info_200 = gmres(A, b, callback = IterCount())
5 gmres_res = closure_variables["residuals"]
NameError: name 'mat' is not defined
As far as I'm aware, it should be defined when I call the DiscretiseEquation function?
I'm trying to do OOP in Lua, but it's not letting me change the vel_y value in the checkInput{} method. Any ideas how i can get this to work? By the way I'm using Love2D for this input stuff.
Player = {x = 100, y = 20, vel_x = 0, vel_y = 0}
function Player:new(o, x, y, vel_x, vel_y)
o = o or {} -- create object if user does not provide one
setmetatable(o, self)
self.__index = self
length = 0
return o
end
function Player:getX()
return self.x
end
function Player:getY()
return self.y
end
function Player:update( dt )
--update velocity
self.x = self.x + self.vel_x
self.y = self.y + self.vel_y
checkInput()
end
function checkInput( dt )
if love.keyboard.isDown("w") and length < 5 then --press the right arrow key to push the ball to the right
length = length + 1
self.vel_y = 5
print("bruhddddddddddddddddddddddd")
elseif love.keyboard.isDown("a") then
elseif love.keyboard.isDown("s") then
elseif love.keyboard.isDown("d") then
end
end
I assume your system call player:update() firs? If so you should pass self and dt to checkInput
function Player:update( dt )
--update velocity
self.x = self.x + self.vel_x
self.y = self.y + self.vel_y
checkInput(self, dt) --<--
end
...
function checkInput( self, dt )
...
if you define checkInput as local (of course before Player:update) this may be similar to private method.
Player = {x = 100, y = 20, vel_x = 0, vel_y = 0} do
Player.__index = self -- we can do this only once
function Player:new(o, x, y, vel_x, vel_y)
o = setmetatable(o or {}, self) -- create object if user does not provide one
-- init o here
return o
end
function Player:getX() end
function Player:getY() end
-- Private method
local function checkInput(self, dt) end
function Player:update( dt )
...
checkInput(self, dt) -- call private method
end
end -- end clsss defenitioin