How can I generate random parameters in AMPL? Here is my code:
set P;set R;param T>0 integer;
param k {p in P} > 0;param z {r in R} > 0;param c1 >= 0;param c2 >= 0;param c3 >= 0;param h >= 0;param f >= 0;param v >= 0;param D {t in 1..T, p in P} >= 0; param Dr{t in 1..T, r in R} >= 0;param M {t in 1..T, p in P} > 0;param O {t in 1..T, p in P} > 0;
var m {t in 1..T, p in P} >= 0;var n {t in 1..T, r in P} >= 0;var o {t in 1..T, p in P} >= 0;var a {t in 1..T, p in P} >= 0;var d {t in 1..T, p in P} >= 0;var s {t in 1..T, p in P} >= 0;
maximize profit: sum {t in 1..T} sum {p in P} k[p]* m[t,p] + sum{t in 1..T} sum {r in R}z[r]*n[t,r] - (c1*sum {t in 1..T} sum {p in P} m[t,p] + c2 *sum {t in 1..T} sum {r in R} n[t,r] + c3 * sum {t in 1..T} sum {p in P} o[t,p] + h * sum {t in 1..T} sum {p in P} a[t,p] + f * sum {t in 1..T} sum {p in P} d[t,p] + v * sum {t in 1..T} sum {p in P} s[t,p]);
subject to regular capacity {p in P, t in 1..T}: m[t,p] <= M[t,p];
subject to overrate capacity {t in 1..T, p in P}: o[t,p] <= O[t,p];
subject to inventory balance {t in 1..T, p in P}: s[t,p] = s[t-1,p] + m[t,p] + o[t,p] - D[t,p];
subject to increasing limit {t in 1..T, p in P}: a[t,p] >= m[t,p] - m[t-1,p];
subject to decreasing limit {t in 1..T, p in P}: d[t,p] >= m[t-1,p] - m[t,p];
subject to refurbishing limit {t in 1..T, r in R, p in P}: n[t,r] <= 0.2 * m[t,p];
subject to demand balance {t in 1..T, p in P}: m[t,p] = D[t,p];
subject to demand balance {t in 1..T, r in R}: n[t,r] <= Dr[t,r];
Here are the given sets:
set P and R from 1 to 5 and T from 1 to 12
How can I randomly generate parameters other parameters based on this information?
https://ampl.com/faqs/how-do-i-solve-a-series-of-different-random-problems-with-data-drawn-from-the-same-distribution/ gives this code example:
param avail_mean {STAGE} >= 0;
param avail_variance {STAGE} >= 0;
param avail {s in STAGE} :=
Normal (avail_mean[s], avail_variance[s]);
See section 7.6 of the AMPL Book and Table A3 for documentation on the different random functions available.
Related
I'm not quite sure why my merge-sort implementation is not working.
merge_sort takes as arguments an array A, and starting and final indices p and r. If I try to run merge_sort(A, 1, 9) on A = [1, 64, 64, 315, 14, 2, 3, 4, 5], A will become A = [1, 1, 1, 1, 1, 2, 2, 4, 5]. I'm trying to use a sentinel to detect whether the L and R arrays have been exhausted.
Here is the code:
function merge_sort(A, p, r)
if p < r
q = floor(Int, (p+r)/2)
merge_sort(A, p, q)
merge_sort(A, q+1, r)
merge(A, p, q, r)
end
end
function merge(A, p, q, r)
n1 = q-p+1
n2 = r-q
L = []
R = []
for i = 1:n1
push!(L, A[p+1-1])
end
for j = 1:n2
push!(R, A[q+j])
end
sentinel = 123456789
push!(L, sentinel)
push!(R, sentinel)
i=1
j=1
for k=p:r
if L[i] <= R[j]
A[k] = L[i]
i = i+1
else
A[k] = R[j]
j = j+1
end
end
end
You have a typo in push!(L, A[p+1-1]) which should be push!(L, A[p+i-1]).
Here is a bit cleaned up version of your code (but I did not try to fully optimize it to retain your logic):
function merge_sort!(A, p = 1, r = length(A))
if p < r
q = div(p+r, 2)
merge_sort!(A, p, q)
merge_sort!(A, q+1, r)
merge!(A, p, q, r)
end
A
end
function merge!(A, p, q, r)
sentinel = typemax(eltype(A))
L = A[p:q]
R = A[(q+1):r]
push!(L, sentinel)
push!(R, sentinel)
i, j = 1, 1
for k in p:r
if L[i] <= R[j]
A[k] = L[i]
i += 1
else
A[k] = R[j]
j += 1
end
end
end
I wrote levenshtein_distance as below to calculate the distance between two strings:
def min3(a, b, c)
if a < b && a < c then
a
elsif b < c then
b
else
c
end
end
def levenshtein_distance(s, t)
m = s.length
n = t.length
return m if n.zero?
return n if m.zero?
d = (0..m+1).to_a
x = nil
s.each_char.each_with_index do |ch1, i|
e = i + 1
t.each_char.each_with_index do |ch2, j|
cost = ch1 == ch2 ? 0 : 1
x = min3(d[j + 1] + 1, e + 1, d[j] + cost)
d[j] = e
e = x
end
d[m] = x
end
x
end
When the two strings are different, it gives an error message:
NoMethodError - undefined method `+' for nil:NilClass
The error detects line:
x = min3(d[j + 1] + 1, e + 1, d[j] + cost)
I thought this was due to index surpassing the defined d's limit. But enlarging the length of d doesn't solve this problem.
Is there something I missed in implementing the algorithm?
this is the case that I tested on irb
irb(main):052:0> levenshtein_distance("a", "abc")
NoMethodError: undefined method `+' for nil:NilClass
from (irb):24:in `block (2 levels) in levenshtein_distance'
from (irb):22:in `each_char'
from (irb):22:in `each_with_index'
from (irb):22:in `block in levenshtein_distance'
from (irb):20:in `each_char'
from (irb):20:in `each_with_index'
from (irb):20:in `levenshtein_distance'
from (irb):52
from /usr/bin/irb:12:in `<main>'
I've rewritten the algorithm in accordance to Wikipedia:
def ld(s, t)
v0 = (0..t.length).to_a
v1 = []
#p v0
s.chars.each_with_index do |s_ch, i|
v1[0] = i + 1
t.chars.each_with_index do |t_ch, j|
cost = s_ch == t_ch ? 0 : 1
v1[j + 1] = [v1[j] + 1, v0[j + 1] + 1, v0[j] + cost].min
end
v0 = v1.dup
#p v1
end
v0[t.length]
end
It seem to work. Also you can as well uncomment p v1 and p v0 to see how the vectors change on each iteration.
I am trying to test a binary search algorithm. The logic seems right, however, I'm running into some issues.
There are two different methods, case and if. If one method fails, the other is right.
1.
arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
def search(arr, value)
if arr.nil?
return "value not in array"
end
l = 0
u = (arr.length - 1)
t = value
if l > u
puts "array is wrong!"
return
end
while l < u
m = (l + u) / 2
case m
when m < t
l = (m + 1)
when m == t
puts "hello world"
when m > t
u = (m - 1)
end
end
end
search(arr, 5)
2.
def search(arr, value)
if arr.nil?
return "value not in array"
end
l = 0
u = (arr.length - 1)
t = value
if l > u
puts "array is wrong!"
return
end
while l < u
m = (l + u) / 2
if m < t
l = (m + 1)
elsif m == t
puts "hello world"
break
elsif m > t
u = (m - 1)
end
end
end
I thought my code would work, but something is causing my while loop to go on infinitely. What am I doing to cause an infinite loop?
I'm implementing an HSV to RGB function in ruby, and I was hoping for syntax like this:
def hsv_to_rgb(h, s, v)
if (h == 0) then return 0, 0, 0 end
c = v * s
hp = h / 60.0
x = c * (1 - (hp % 2 - 1).abs)
r, g, b = case hp
when 0..1
c, x, 0
when 1..2
x, c, 0
when 2..3
0, c, x
when 3..4
0, x, c
when 4..5
x, 0, c
else
c, 0, x
end
m = v - c
return r + m, g + m, b + m
end
however, when I attempt to run this in Jruby I get the following error message:
SyntaxError: julia2.rb:60: syntax error, unexpected '\n'
when 1..2
Does something like this syntax exist in ruby?
Thanks!
Your return values in the case statement are not accepted by the ruby engine. I think you want to return an array... using the [] perhaps?
Like this:
def hsv_to_rgb(h, s, v)
if (h == 0) then return 0, 0, 0 end
c = v * s
hp = h / 60.0
x = c * (1 - (hp % 2 - 1).abs)
r, g, b = case hp
when 0..1
[c, x, 0]
when 1..2
[x, c, 0]
when 2..3
[0, c, x]
when 3..4
[0, x, c]
when 4..5
[x, 0, c]
else
[c, 0, x]
end
m = v - c
return r + m, g + m, b + m
end
Returning array will work and it is more readable as well.
I need to improve the performance of this algorithm. I believe the answer lies in the application of the pisano period.
This algorithm must return the last digit of the sum of fib numbers from f(m) to f(n).
Here is what I have so far:
def fib(n)
a = []
a << 0 << 1
(n+1).times do |i|
a << a[-1] + a[-2]
end
a[n]
end
def fib_partial_sum(m, n)
if n == m
fib(m) % 10
else
m = fib(m + 1) - 1
n = fib(n + 2) - 1
(n - m) % 10
end
end
if __FILE__ == $0
m, n = gets.split().map(&:to_i)
puts "#{fib_partial_sum(m, n)}"
end
The last digit of any fib num repeats every 60 numbers. Therefore, we can do this, n, m = n % 60, m % 60. An improvement, but not quite there yet, fails on input 567717153638 567717153638):
def fib(n)
a = []
a << 0 << 1
(n+1).times do |i|
a << a[-1] + a[-2]
end
a[n]
end
def fib_partial_sum(m, n)
if n == m
fib(m)
else
m = m % 60
n = n % 60
m = fib(m + 1) - 1
n = fib(n + 2) - 1
(n - m) % 10
end
end
if __FILE__ == $0
m, n = gets.split().map(&:to_i)
puts "#{fib_partial_sum(m, n)}"
end
Here is a nice solution to the problem, it passes all time and memory constraints.
This way you never have to calculate a fib num greater that f(60). It can handle very large inputs efficiently.
def fib(n)
a, b = 0, 1
(n-1).times do
a, b = b, (a + b) % 10
end
b
end
def fib_partial_sum(m, n)
if n == m
fib(m % 60)
else
m = m % 60
n = n % 60
m = fib(m + 1) - 1
n = fib(n + 2) - 1
(n - m) % 10
end
end
if __FILE__ == $0
m, n = gets.split().map(&:to_i)
puts "#{fib_partial_sum(m, n)}"
end
(Max time used: 0.05/5.00, max memory used: 8699904/536870912.)
The following requires only a single pass of the numbers between zero and at most [n,m+60].min, where m..n is the range of interest, and has a minimal memory requirement. It makes use of #nloveladyallen's observation that the last digit of Fibonacci numbers has a periodicity of 60.
Code
def fib_last(m,n)
n -= 60*((n-m)/60)
fib_sum(m,n) % 10
end
def fib_sum(m,n)
return nil if m < 0 || m > n
return n if n < 2
next_to_last, last = fib(m-1)
(m..n).reduce(0) do |tot,_|
current = next_to_last + last
next_to_last = last
last = current
tot + current
end
end
def fib(m)
next_to_last, last = -1, 1
0.upto(m).each do |n|
current = next_to_last + last
next_to_last, last = last, current
end
[next_to_last, last]
end
Example
m, n = 6, 12
(n+1).times { |i| puts "#{i}: #{fib(i)}" }
0: [0, 0]
1: [0, 1]
2: [1, 1]
3: [1, 2]
4: [2, 3]
5: [3, 5]
6: [5, 8]
7: [8, 13]
8: [13, 21]
9: [21, 34]
10: [34, 55]
11: [55, 89]
12: [89, 144]
fib_last(6,12) #=> 4 (fib_sum(6,12) #=> 8 + 13 + 21 + 34 + 55 + 89 + 144 = 364)
fib_last(1,2) #=> 2 (fib_sum(1,2) #=> 1 + 1 = 2)
fib_last(1,3) #=> 4 (fib_sum(1,3) #=> 1 + 1 + 2 = 4)
fib_last(1,4) #=> 7 (fib_sum(1,4) #=> 1 + 1 + 2 + 3 = 7)
fib_last(2,3) #=> 3 (fib_sum(2,3) #=> 1 + 2 = 3)