diff --git a/problems/so3-synthetic.py b/problems/so3-synthetic.py index 5a283a34dded7dac711930b670ffbfd7e6bd9bad..206e197dca2f62b9ba6c224500122652e585fc65 100644 --- a/problems/so3-synthetic.py +++ b/problems/so3-synthetic.py @@ -46,7 +46,132 @@ def matrixToQuaternion(m): return p +# Takes a 3 x 3 object, returns a 4 x 3 x 3 object +def derivativeOfMatrixToQuaternion(m): + + result = [[[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], + [0,0,0]]] + + p = [(1 + m[0][0] - m[1][1] - m[2][2]) / 4, + (1 - m[0][0] + m[1][1] - m[2][2]) / 4, + (1 - m[0][0] - m[1][1] + m[2][2]) / 4, + (1 + m[0][0] + m[1][1] + m[2][2]) / 4] + # avoid rounding problems + if (p[0] >= p[1] and p[0] >= p[2] and p[0] >= p[3]): + + result[0] = [[1,0,0],[0,-1,0],[0,0,-1]] + for i in range(0,3): + for j in range(0,3): + result[0][i][j] *= 1.0/(8.0*sqrt(p[0])) + + denom = 32 * pow(p[0],1.5) + offDiag = 1.0/(4*sqrt(p[0])) + + result[1] = [ [-(m[0][1]+m[1][0]) / denom, offDiag, 0], + [offDiag, (m[0][1]+m[1][0]) / denom, 0], + [0, 0, (m[0][1]+m[1][0]) / denom]] + + result[2] = [ [-(m[0][2]+m[2][0]) / denom, 0, offDiag], + [0, (m[0][2]+m[2][0]) / denom, 0], + [offDiag, 0, (m[0][2]+m[2][0]) / denom]] + + result[3] = [ [-(m[2][1]-m[1][2]) / denom, 0, 0], + [0, (m[2][1]-m[1][2]) / denom, -offDiag], + [0, offDiag, (m[2][1]-m[1][2]) / denom]] + + elif (p[1] >= p[0] and p[1] >= p[2] and p[1] >= p[3]): + + result[1] = [[-1,0,0],[0,1,0],[0,0,-1]] + for i in range(0,3): + for j in range(0,3): + result[1][i][j] *= 1.0/(8.0*sqrt(p[1])) + + denom = 32 * pow(p[1],1.5) + offDiag = 1.0/(4*sqrt(p[1])) + + result[0] = [ [(m[0][1]+m[1][0]) / denom, offDiag, 0], + [offDiag, -(m[0][1]+m[1][0]) / denom, 0], + [0, 0, (m[0][1]+m[1][0]) / denom]] + + result[2] = [ [(m[1][2]+m[2][1]) / denom, 0 , 0], + [0, -(m[1][2]+m[2][1]) / denom, offDiag], + [0, offDiag, (m[1][2]+m[2][1]) / denom]] + + result[3] = [ [(m[0][2]-m[2][0]) / denom, 0, offDiag], + [0, -(m[0][2]-m[2][0]) / denom, 0], + [-offDiag, 0, (m[0][2]-m[2][0]) / denom]] + + elif (p[2] >= p[0] and p[2] >= p[1] and p[2] >= p[3]): + + result[2] = [[-1,0,0],[0,-1,0],[0,0,1]] + for i in range(0,3): + for j in range(0,3): + result[2][i][j] *= 1.0/(8.0*sqrt(p[2])) + + denom = 32 * pow(p[2],1.5) + offDiag = 1.0/(4*sqrt(p[2])) + + result[0] = [ [(m[0][2]+m[2][0]) / denom, 0, offDiag], + [0, (m[0][2]+m[2][0]) / denom, 0], + [offDiag, 0, -(m[0][2]+m[2][0]) / denom]] + + result[1] = [ [(m[1][2]+m[2][1]) / denom, 0 , 0], + [0, (m[1][2]+m[2][1]) / denom, offDiag], + [0, offDiag, -(m[1][2]+m[2][1]) / denom]] + + result[3] = [ [(m[1][0]-m[0][1]) / denom, -offDiag, 0], + [offDiag, (m[1][0]-m[0][1]) / denom, 0], + [0, 0, -(m[1][0]-m[0][1]) / denom]] + + else: + + result[3] = [[1,0,0],[0,1,0],[0,0,1]] + for i in range(0,3): + for j in range(0,3): + result[3][i][j] *= 1.0/(8.0*sqrt(p[3])) + + denom = 32 * pow(p[3],1.5) + offDiag = 1.0/(4*sqrt(p[3])) + + result[0] = [ [-(m[2][1]-m[1][2]) / denom, 0, 0], + [0, -(m[2][1]-m[1][2]) / denom, -offDiag], + [0, offDiag, -(m[2][1]-m[1][2]) / denom]] + + result[1] = [ [-(m[0][2]-m[2][0]) / denom, 0, offDiag], + [0, -(m[0][2]-m[2][0]) / denom, 0], + [-offDiag, 0, -(m[0][2]-m[2][0]) / denom]] + + result[2] = [ [-(m[1][0]-m[0][1]) / denom, -offDiag, 0], + [offDiag, -(m[1][0]-m[0][1]) / denom, 0], + [0, 0, -(m[1][0]-m[0][1]) / denom]] + + return result + + + +def mult(m1,m2): + m = [[0,0,0], + [0,0,0], + [0,0,0]] + + # Matrix-matrix multiplication by hand -- for some reason I cannot get numpy to work + for i in range(0,3): + for j in range(0,3): + for k in range(0,3): + m[i][j] = m[i][j] + m1[i][k] * m2[k][j] + + return m def f(x): @@ -61,20 +186,48 @@ def f(x): [sin(beta), cos(beta), 0], [0, 0, 1]] - m = [[0,0,0], - [0,0,0], - [0,0,0]] - - # Matrix-matrix multiplication by hand -- for some reason I cannot get numpy to work - for i in range(0,3): - for j in range(0,3): - for k in range(0,3): - m[i][j] = m[i][j] + rotationX[i][k] * rotationZ[k][j] + m = mult(rotationX,rotationZ) return matrixToQuaternion(m) -# Should never be called def df(x): - return [[0,0],[0,0],[0,0],[0,0]] + + alpha = 2*math.pi*x[0] + beta = 2*math.pi*x[1] + + rotationX = [[1, 0, 0], + [0, cos(alpha), -sin(alpha)], + [0, sin(alpha), cos(alpha)]] + + derRotX = [[0, 0, 0], + [0, -2*math.pi*sin(alpha), -2*math.pi*cos(alpha)], + [0, 2*math.pi*cos(alpha), -2*math.pi*sin(alpha)]] + + rotationZ = [[cos(beta), -sin(beta), 0], + [sin(beta), cos(beta), 0], + [0, 0, 1]] + + derRotZ = [[-2*math.pi*sin(beta), -2*math.pi*cos(beta), 0], + [ 2*math.pi*cos(beta), -2*math.pi*sin(beta), 0], + [0, 0, 0]] + + # The function value as matrix + # CAREFUL! We are reimplementing method 'f' here -- the two implementations need to match! + value = mult(rotationX,rotationZ) + + derX0 = mult(derRotX,rotationZ) + derX1 = mult(rotationX,derRotZ) + + derOfMatrixToQuaternion = derivativeOfMatrixToQuaternion(value) + + result = [[0,0],[0,0],[0,0],[0,0]] + + for i in range(0,4): + for j in range(0,3): + for k in range(0,3): + result[i][0] += derOfMatrixToQuaternion[i][j][k] * derX0[j][k] + result[i][1] += derOfMatrixToQuaternion[i][j][k] * derX1[j][k] + + return result fdf = (f, df)