Skip to content

Commit caddc1c

Browse files
committedMar 7, 2017
fixed errors in rosenbrock
1 parent f4d9c91 commit caddc1c

File tree

6 files changed

+96
-24
lines changed

6 files changed

+96
-24
lines changed
 

‎.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
*.o
22
*.so
3-
fuse_problem
3+
fuse.problem
44
.fuse_hidden*

‎Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ all: fuse.problem
3636
$(GXX) $(LDFLAGS) -o fuse.problem problem.o fuse.problem.o
3737

3838
fuse.problem: problem
39-
$(GCC) -c main.c $(CFLAGS) $(CFUSE) -o fuse.problem.o
39+
$(GCC) -c src/main.c $(CFLAGS) $(CFUSE) -o fuse.problem.o
4040

4141
problem:
4242
$(GXX) -c src/problem.cpp $(CFLAGS) -o problem.o

‎README.md

+36-2
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,39 @@ File system **must** always be unmounted, or it will continue to run in backgrou
8585

8686
## Example
8787

88-
Let's run `librosenbrock` to test usage, with a ruby script that reads and writes files.
89-
TO BE FINISHED
88+
Let's run `librosenbrock` to test usage, with a ruby script that reads and writes files. The script implements a Newton method on the Rosenbrock function.
89+
90+
The necessary file system is loaded as:
91+
```sh
92+
make all
93+
make rosenbrock
94+
95+
./fuse.problem -s /tmp/mount shared/librosenbrock.so
96+
```
97+
98+
Then `rosenbrock.rb` can be run as test problem. The core elements to interface file system with Ruby language are the three functions:
99+
```ruby
100+
def write(x)
101+
File.open($x, "w") { |xf| xf.puts x.map(&:to_s).join("\n") }
102+
end
103+
```
104+
for writing a new value (it also triggers a re-evaluation),
105+
```ruby
106+
def write_p(p)
107+
File.open($p, "w") { |pf| pf.puts p.map(&:to_s).join("\n") }
108+
end
109+
```
110+
for writing a parameter, and
111+
```ruby
112+
def read()
113+
return [
114+
File.open($df, "r").read.chomp.split("\n").map(&:to_f),
115+
File.open($ddf, "r").read.chomp.split("\n").map(&:to_f)
116+
]
117+
end
118+
119+
# [...]
120+
121+
File.open($f, "r").read.chomp
122+
```
123+
for reading gradient, hessian (function `read`) and reading the function value (the last line).

‎include/problem.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ template <class FP> class Problem {
120120
map<string, int> paths; /**< path to internal representation (enums) mapping */
121121

122122
size_t x_s; /**< declared dimension for input x */
123-
size_t p_s /**< declared dimension for parameter p */
123+
size_t p_s; /**< declared dimension for parameter p */
124124
size_t f_s; /**< number of function declared in shared object */
125125

126126
vector<Function> f; /**< vector of function pointer */

‎shared/librosenbrock.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
* $$
4343
* \\nabla f = \\left[
4444
* \\begin{array}{c}
45-
* 4 a x^3 - 4 b x y - 2 a + 2 x \\\\
46-
* 3 b (y - x^2)
45+
* 2 x - 2 a - 4 b x (-x^2 + y) \\\\
46+
* 2 b (y - x^2)
4747
* \\end{array}
4848
* \\right]
4949
* $$
@@ -53,8 +53,10 @@
5353
* $$
5454
* \\nabla ^2 f = \\left[
5555
* \\begin{array}{cc}
56-
* 2 + (12 x - 4 y) b & -4 b x \\\\
57-
* -4 b x & 2 b
56+
* 2 + 8 b x^2 - 4 b (-x^2 + y) - 4 b x &
57+
* -4 b x \\\\
58+
* -4 b x &
59+
* 2 b
5860
* \\end{array}
5961
* \\right]
6062
* $$
@@ -97,7 +99,7 @@ FUNCTION_DEFINE(f_rosenbrock, {
9799
FUNCTION_DEFINE(df_rosenbrock, {
98100
Y().clear();
99101
Y().push_back(
100-
4.0 * P()[1] * pow(X()[0], 3.0) - 4.0 * P()[1] * X()[0] * X()[1] - 2.0 * P()[0] + 2.0 * X()[0]
102+
2 * X()[0] - 2 * P()[0] - 4 * P()[1] * X()[0] * (-pow(X()[0], 2.0) + X()[1])
101103
);
102104
Y().push_back(
103105
2.0 * P()[1] * (X()[1] - pow(X()[0], 2.0))
@@ -110,7 +112,7 @@ FUNCTION_DEFINE(ddf_rosenbrock, {
110112
PROBLEM_PRECISION ddf01 = -4.0 * P()[1] * X()[0];
111113

112114
Y().push_back(
113-
2.0 + (12.0 * pow(X()[0], 2.0) - 4.0 * X()[1]) * P()[1]
115+
2.0 + 8.0 * P()[1] * pow(X()[0], 2) - 4 * P()[1] * (X()[1] - pow(X()[0], 2))
114116
);
115117
Y().push_back(ddf01);
116118
Y().push_back(ddf01);

‎shared/rosenbrock.rb

+49-13
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,75 @@
55
# dimensions and we already know that f returns only a
66
# value, while gradient returns a vector.
77

8-
$mount = "/tmp/mount/"
8+
$mount = "/tmp/mount/" # base mountpoint
99
$x = $mount + "x" # path for input
1010
$p = $mount + "p" # path for parameters
11+
$f = $mount + "y0" # path for function
1112
$df = $mount + "y1" # path for gradient
1213
$ddf = $mount + "y2" # path for hessian
1314

1415
# The next function only writes new parameters
1516
# in parameter file
1617
def write_p(p)
17-
File.open($p, "w") do |pf|
18-
pf.puts p.map(&:to_s).join("\n")
19-
end
18+
File.open($p, "w") { |pf| pf.puts p.map(&:to_s).join("\n") }
2019
end
2120

2221
# The next function only writes new input to the input
2322
# file
2423
def write(x)
25-
File.open($x, "w") do |xf|
26-
xf.puts x.map(&:to_s).join("\n")
27-
end
24+
File.open($x, "w") { |xf| xf.puts x.map(&:to_s).join("\n") }
2825
end
2926

3027
# The next function reads the gradient and hessian, thus returns
31-
# an array of array of values
28+
# an array of array of values. This is what we need to evaluate a
29+
# Newton algorithm
3230
def read()
33-
df = Files($df, "r").read.chomp.split("\n").map(&:to_f)
34-
ddf = Files($ddf, "r").read.chomp.split("\n").map(&:to_f)
35-
return df, ddf
31+
return [
32+
File.open($df, "r").read.chomp.split("\n").map(&:to_f),
33+
File.open($ddf, "r").read.chomp.split("\n").map(&:to_f)
34+
]
3635
end
3736

37+
# This function performs a newton step in the form:
38+
#
39+
# x[+] = x - (hessian(f)(x))^(-1) gradient(f)(x)
3840
def newton_step(x, df, ddf)
41+
dt = 1.0 / (ddf[0] * ddf[3] - ddf[1] * ddf[2])
3942
return [
40-
x[0] - (ddf[0] * df[0] + ddf[1] * df[1]),
41-
x[1] - (ddf[2] * df[0] + ddf[3] * df[1])
43+
x[0] - dt * (ddf[3] * df[0] - ddf[2] * df[1]),
44+
x[1] - dt * (ddf[0] * df[1] - ddf[1] * df[0])
4245
]
4346
end
47+
48+
# Evaluates the norm two of 2D vectors
49+
def norm(a, b)
50+
return ((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** (0.5)
51+
end
52+
53+
if __FILE__ == $0
54+
# Maximum iteration
55+
ITERMAX = 1000
56+
# Tolerance. If ||x[+] - x|| < tol we stop execution
57+
# of iterative algorithm.
58+
TOL = 1e-5
59+
60+
# Starting Point
61+
x = z = [0.0, 0.0]
62+
# Parameter configuration and write configuration
63+
write_p([1.0, 100.0])
64+
65+
# Newton Algorithm
66+
i = 0
67+
for i in (0..ITERMAX)
68+
write(z) # write will evaluate again the function
69+
puts(z.map(&:to_s).join(","))
70+
df, ddf = read()
71+
z = newton_step(x, df, ddf)
72+
break if norm(z, x) < TOL
73+
end
74+
75+
# Print on screen results
76+
puts "Itermax reached" if i == ITERMAX
77+
puts "Solution (after #{i} iterations):"
78+
puts " f(#{z.map(&:to_s).join(", ")}) = #{File.open($f, "r").read.chomp}"
79+
end # __FILE__ == $0

0 commit comments

Comments
 (0)
Please sign in to comment.