I have a problem with my prescription of a mathematical problem to AMPL.
I trying to solve this problem:
In a network with a set of nodes N and a set of edges E each node has storage to cache content. There is a set O of content objects that are accesses by the clients and can be cached if needed. Let the size of o ∈ O be equal to h_o storage units. Assume each node n ∈ N has clients that request object o ∈ O so that the traffic towards n to download o equals d_n;o. In a managed content delivery network (CDN), the CDN operator can adopt various policies to allocate content copies among the caches. These policies may depend on many factors that can be technical or business in nature, which gives rise to dierent optimisation problems. Let h_max be the maximum total storage that can be used by the CDN (i.e., the sum of storage used bythe CDN over all nodes). Find: the allocation of copies of each object o ∈ O such that the limit on the total storage used by CDN is satised while minimising the overall trac in the network (i.e., the routing cost from the caches to client nodes)
Ampl Files:
#Model for 'CDN allocation copies' problem
#sets
#-------------------------------------------------------------------------------------
set K; #index of nodes with group of clients
set N; #nodes
set E; #edges
set O; #objects
#parameters
#-------------------------------------------------------------------------------------
param d {K,O}; #demands for object o
param t {K,O} symbolic; #destination nodes
param r {N,K} binary; #1 if node n is ancestor of node k, 0 otherwise
param a {N,E} binary; #1 if edge begins in vertex, 0 otherwise
param b {N,E} binary; #1 if edge ends in vertex, 0 otherwise
param c {E}; #cost of using an edge
param Hmax; #available capacity for allocation object in proxy servers
#variables
#-------------------------------------------------------------------------------------
var f {N,O} binary; #1 if object saved at node k, 0 otherwise
var x {E,K,O}; #value of the demand realised over edge for object
#goal function
#-------------------------------------------------------------------------------------
#The function minimizes cost of routing
#By saving copies at CDN proxies we minimizing all traffic from all demands
#with all objects
minimize goal:
sum{e in E}
sum{k in K}
sum{o in O}
(x[e,k,o]*c[e]);
#constraints
#-------------------------------------------------------------------------------------
subject to c0 {e in E, k in K, o in O}:
x[e,k,o]>=0;
subject to c1a {k in K, o in O, n in N: n!=t[k,o]}:
(r[n,k]==1 and f[n,o]==1)
==>
sum{e in E}
(a[n,e]*x[e,k,o]) -
sum{e in E}
(b[n,e]*x[e,k,o]) =
d[k,o]*(1-f[k,o])
else
sum{e in E}
(a[n,e]*x[e,k,o]) -
sum{e in E}
(b[n,e]*x[e,k,o]) =
0;
subject to c1c {k in K, o in O, n in N: n==t[k,o]}:
sum{e in E}
(a[n,e]*x[e,k,o]) -
sum{e in E}
(b[n,e]*x[e,k,o]) =
-d[k,o]*(1-f[k,o]);
subject to c2:
sum{k in K}
sum{o in O}
f[k,o] <= Hmax;
subject to c3 {k in K, o in O}:
sum{n in N}
r[n,k]*f[n,o] <= 2;
subject to c4 {o in O}:
f[1,o]=1;
And my data file:
#Data file for 'CDN allocation copies' problem simple example
#indices
set K := 2 3; #index of nodes with group of clients
set N := 1 2 3; #nodes
set E := 1_2 1_3; #edges
set O := o1 o2 o3 o4 o5 o6 o7 o8 o9 o10; #objects
#parameters
param d (tr): #demands for object o
2 3 :=
o1 2560 512
o2 1280 256
o3 640 128
o4 320 64
o5 160 32
o6 80 16
o7 40 8
o8 20 4
o9 10 2
o10 5 1;
#opt= 63 + 75 = 138
param t (tr): #destination nodes
2 3 :=
o1 2 3
o2 2 3
o3 2 3
o4 2 3
o5 2 3
o6 2 3
o7 2 3
o8 2 3
o9 2 3
o10 2 3;
param r (tr): #1 if node n is ancestor of node k, 0 otherwise
1 2 3 :=
2 1 0 0
3 1 0 0;
param a (tr): #1 if edge begins in vertex, 0 otherwise
1 2 3 :=
1_2 1 0 0
1_3 1 0 0;
param b (tr): #1 if edge ends in vertex, 0 otherwise
1 2 3 :=
1_2 0 1 0
1_3 0 0 1;
param c := #cost of using an edge
1_2 1
1_3 1;
param Hmax := 10; #available capacity for allocation object in proxy servers
When I try to solve my problem i see this bug:
Error at _cmdno 15 executing "let" command
(file C:\Program Files\AMPLDevX64 Evaluation\plugins\com.ampldev_2.3.0.201211162252 \include/writesol.ampl, line 22, offset 783):
Can't evaluate _con[92]:
subscript not in 1 .. 91
The error was caused by AMPL incorrectly including the number of logical constraints in _ncons. It is fixed in AMPL version 20130510 (see http://www.netlib.org/ampl/changes). The logical constraint in your model is the indicator constraint c1a.
Related
f(n):
s = 1
m = n
while m >= 1:
for j in 1,2,3, .., m:
s = s + 1
m = m / 2
My attempt
How many times does the statement s = s + 1 run? Well, let's try a number or two for n and see what we get.
n = 32
m = n = 32
m = 32 => inner for loop, loops 32 times
m = 16 => -.- 16 times
m = 8 => -.- 8 times
m = 4 => -.- 4 times
m = 2 => -.- 2 times
m = 1 => -.- 1 time
In total 16+8+4+2+1 = 31 times for n = 32
Doing the same for n = 8 gives 15 times
Doing the same for n = 4 gives 7 times
Doing the same for n = 64 gives 127 times
Notice how it always seemingly is 2 * n - 1, I believe this to be no coincidence because what we're really observing is that the total amount of times the statement gets executed is equal to the geometric sum sum of 2^k from k=0 to k=log(n) which has a closed form solution 2n + 1 given that we're using base 2 logarithm.
As such, my guess is that the complexity is O(n).
Is this correct?
Well what you just observed is true indeed. We can prove it mathematically as well.
Inner loop execution for first iteration -> n
Inner loop execution for second iteration -> n/2
Inner loop execution for third iteration -> n/(2^2)
and so on....
Therfore total time is (n + (n/2) + (n/(2^2)) + ... + (n/(2^k))) where n/(2^k) should be equal to 1 which implies k = log(n). Taking n common from all terms will give us a GP And now using GP formulae in above series , total time will come out to be 1(1 - ((1/2)^k)) / (1 - 1/2). putting value of k = log(n), we will get total time as 2*(n-1).
Note -:
This gives us time complexity of O(n).
log is of base 2.
I have a little confusion in the optimization model I trying to solve. Its a small model to minimize the cost of two units. I have just started with the optimization and I am not sure if I am interpreting the problem very well into AMPL. Especially regarding the minimization constraints and their bounds.
I have to two decision variables as Units in my models. Cost of u1 is 10 and u2 is 13. And the limit on the u1 is that you can not make more than 100 units and for u2 is 50 units. I got different results by reversing the bounds of this minimization problem. Can anyone help me interpret whats happening?
var u1 >=0;
var u2 >=0;
minimize costofunits: 10*u1 +13*u2;
subject to unit1: 0 <= u1 <= 100;
subject to unit2: 0 <= u2 <= 50;
With above constraints I have output as:
CPLEX 12.8.0.0: optimal solution; objective 0
0 dual simplex iterations (0 in phase I)
Objective is: 0.000000
: _varname _var :=
1 u1 0
2 u2 0
;
: _objname _obj :=
1 costofunits 0
;
: _conname _con :=
1 unit1 0
2 unit2 0
;
Reversing the Constraints:
subject to unit1: 100 <= u1 <= 0;
subject to unit2: 50 <= u2 <= 0;
OUTPUT AS:
inconsistent bounds for constraint unit1:
lower bound = 100 > upper bound = 0
inconsistent bounds for constraint unit2:
lower bound = 50 > upper bound = 0
Infeasible constraints determined by presolve.
Objective is: 825.000000
: _varname _var :=
1 u1 50
2 u2 25
;
: _objname _obj :=
1 costofunits 825
;
: _conname _con :=
1 unit1 10
2 unit2 13
;
For your first problem: as you've defined the problem, the objective is to minimize costs, and the easiest solution is simply to make zero of everything, for zero cost.
For your second problem, the error message explains the problem. You have set a lower bound of 100 for u1 (100 <= u1) and also an upper bound of 0 (u1 <= 0). Obviously there is no possible number that would satisfy both of these requirements at once. Instead of "<=" in your constraints, you should be using ">=" here, assuming you want to bound u1 between 100 and 0.
Same issue for unit2 constraint.
Why because of the i=i*2 is the runtime of the loop below considered O(logN)?
for (int i = 1; i <= N;) {
code with O(1);
i = i * 2;
}
Look at 1024 = 210. How many times do you have to double the number 1 to get 1024?
Times 1 2 3 4 5 6 7 8 9 10
Result 2 4 8 16 32 64 128 256 512 1024
So you would have to run your doubling loop ten times to get 210 And in general, you have to run your doubling loop n times to get 2n. But what is n? It's the log2 2n, so in general if n is some power of 2, the loop has to run log2n times to reach it.
To have the algorithm in O(logN), for any N it would need (around) log N steps. In the example of N=32 (where log 32 = 5) this can be seen:
i = 1 (start)
i = 2
i = 4
i = 8
i = 16
i = 32 (5 iterations)
i = 64 (abort after 6 iterations)
In general, after x iterations, i=2^x holds. To reach i>N you need x = log N + 1.
PS: When talking about complexities, the log base (2, 10, e, ...) is not relevant. Furthermore, it is not relevant if you have i <= N or i < N as this only changes the number of iterations by one.
You can prove it pretty simply.
Claim:
For the tth (0 base) iteration, i=2^t
Proof, by induction.
Base: 2^0 = 1, and indeed in the first iteration, i=1.
Step: For some t+1, the value of i is 2*i(t) (where i(t) is the value of i in the t iteration). From Induction Hypothesis we know that i(t)=2^t, and thus i(t+1) = 2*i(t) = 2*2^t = 2^(t+1), and the claim holds.
Now, let's examine our stop criteria. We iterate the loop while i <= N, and from the above claim, that means we iterate while 2^t <= N. By Doing log_2 on both sides, we get log_2(2^t) <= log_2(N), and since log_2(2^t) = t, we get that we iterate while t <= log_2(N) - so we iterate Theta(log_2(N)) times. (And that concludes the proof).
i starts in 1. In each iteration you multiply i by 2, so in the K-th iteration, i will be 2K-1.
After a number K of iterations, 2K-1 will be bigger than (or to) N.
this means N ≤ 2K-1
this means log2(N) ≤ K-1
K-1 will be the number of iterations your loop will run, and since K-1 is greater or equal to log(N), your algorithm is logarithmic.
I'm implementing a semi ELGamal cryptosystem(from a research paper) function that has been used in PVSS. Unfortunately, I fail to decrypt as it has been described in the algorithm.
Here is the initialisation phase:
Select a secure prime p such that p-1=2q where q is also a prime, then make a cyclic group G and let g be a random generator of this group. Pick a random x(private key) in the group and let y = g^x(public key). I simply initialise the algorithm as following:
p = 233;
g = 131;
x = 139;
y = g ^ x mod 233; //y = 182
Now let s (secret) be 23 and we compute our es (encrypted secret):
s = 23
es = y ^ s mod 233// es = 231
In order to decrypt the es, I raise es to the inverse of x(private key), I should return the g ^ s, assume ds is the deciphered value:
ds = es ^ 1/x mod 233 // 1/x = 57, ds = 116
Problem is here, ds is not equal to g ^ s but in theory it should be because:
recall that we encrypted our s as:
es = y ^ s mod 233
and we know that
y = g ^ x mod 233
so,
es = g ^ x ^ s mod 233
Given that,
ds = es ^ 1/x mod 233
// which means:
ds = g ^ x ^ s ^ 1/x mod 233
therefore, I expect to get same result as of g^s (131 ^ 23 mod 233) which must be 182 while what I get as the ds result is 116.
Is there anything wrong with what I'm doing?
When you have:
x * invX = 1 mod p
the following equality is generally not true:
(g ^ x) ^ invX = g mod p
Above expression means multiplying g*g*....*g a certain number of times, x * invX, which is also k * p + 1 according to first modulo relation.
Say your generator has a size n <= p-1:
g ^ n = 1 mod p
That means that x * invX must be a multiple of n...
In your preamble, you assert that q=(p-1)/2 is prime, but here, it's not the case, q=116...
And in your example g=131 is generating a sequence of length 58=(p-1)/4.
Then, only those x have the property g ^ x ^(1/x) = 1 mod p :
58 116 132 154 174 203 229 231 232
Note that for another generator, g=5, the sequence is of maximal length p-1, and then the sole x satisfying (g ^ x) ^ invX = 1 mod p is x=p-1.
Since y^(p-1) = 1 mod p for any y non multiple of p, x=p-1 is allways working as you expect anyway...
Here's a simple program that blows my heap to Kingdom Come:
intersect n k z s rs c
| c == 23 = rs
| x == y = intersect (n+1) (k+1) (z+1) (z+s) (f : rs) (c+1)
| x < y = intersect (n+1) k (z+1) s rs c
| otherwise = intersect n (k+1) z s rs c
where x = (2*n*n) + 4 * n
y = (k * k + k )
f = (z, (x `div` 2), (z+s))
p = intersect 1 1 1 0 [] 0
main = do
putStr (show p)
What the program does is calculate the intersection of two infinite series, stopping when it reaches 23 elements. But that's not important to me.
What's interesting is that as far as I can tell, there shouldn't be much here that is sitting on the heap. The function intersect is recursives with all recursions written as tail calls. State is accumulated in the arguments, and there is not much of it. 5 integers and a small list of tuples.
If I were a betting person, I would bet that somehow thunks are being built up in the arguments as I do the recursion, particularly on arguments that aren't evaluated on a given recursion. But that's just a wild hunch.
What's the true problem here? And how does one fix it?
If you have a problem with the heap, run the heap profiler, like so:
$ ghc -O2 --make A.hs -prof -auto-all -rtsopts -fforce-recomp
[1 of 1] Compiling Main ( A.hs, A.o )
Linking A.exe ...
Which when run:
$ ./A.exe +RTS -M1G -hy
Produces an A.hp output file:
$ hp2ps -c A.hp
Like so:
So your heap is full of Integer, which indicates some problem in the accumulating parameters of your functions -- where all the Integers are.
Modifying the function so that it is strict in the lazy Integer arguments (based on the fact you never inspect their value), like so:
{-# LANGUAGE BangPatterns #-}
intersect n k !z !s rs c
| c == 23 = rs
| x == y = intersect (n+1) (k+1) (z+1) (z+s) (f : rs) (c+1)
| x < y = intersect (n+1) k (z+1) s rs c
| otherwise = intersect n (k+1) z s rs c
where x = (2*n*n) + 4 * n
y = (k * k + k )
f = (z, (x `div` 2), (z+s))
p = intersect 1 1 1 0 [] 0
main = do
putStr (show p)
And your program now runs in constant space with the list of arguments you're producing (though doesn't terminate for c == 23 in any reasonable time).
If it is OK to get the resulting list reversed, you can take advantage of Haskell's laziness and return the list as it is computed, instead of passing it recursively as an accumulating argument. Not only does this let you consume and print the list as it is being computed (thereby eliminating one space leak right there), you can also factor out the decision about how many elements you want from intersect:
{-# LANGUAGE BangPatterns #-}
intersect n k !z s
| x == y = f : intersect (n+1) (k+1) (z+1) (z+s)
| x < y = intersect (n+1) k (z+1) s
| otherwise = intersect n (k+1) z s
where x = (2*n*n) + 4 * n
y = (k * k + k )
f = (z, (x `div` 2), (z+s))
p = intersect 1 1 1 0
main = do
putStrLn (unlines (map show (take 23 p)))
As Don noted, we need to be careful so that accumulating arguments evaluate timely instead of building up big thunks. By making the argument z strict we ensure that all arguments will be demanded.
By outputting one element per line, we can watch the result being produced:
$ ghc -O2 intersect.hs && ./intersect
[1 of 1] Compiling Main ( intersect.hs, intersect.o )
Linking intersect ...
(1,3,1)
(3,15,4)
(10,120,14)
(22,528,36)
(63,4095,99)
(133,17955,232)
(372,139128,604)
(780,609960,1384)
...