Carl Love

Carl Love

28035 Reputation

25 Badges

12 years, 319 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are answers submitted by Carl Love

I took the information from the StackExchange article that you referenced and use it to write the procedure LinearizeAbsObj below. Then I used that to resolve the same problem as an ILP with Optimization:-LPSolve. Now the solution is almost instantaneous (16 ms).
 

restart:

Data:= <name, x, y, pop;
        A, 3, 7, 5;  B, 6, 5, 2;  C, 5, 3, 2;
        D, 1, 2, 1;  E, 7, 1, 3              >;

Data := Matrix(6, 4, {(1, 1) = name, (1, 2) = x, (1, 3) = y, (1, 4) = pop, (2, 1) = A, (2, 2) = 3, (2, 3) = 7, (2, 4) = 5, (3, 1) = B, (3, 2) = 6, (3, 3) = 5, (3, 4) = 2, (4, 1) = C, (4, 2) = 5, (4, 3) = 3, (4, 4) = 2, (5, 1) = D, (5, 2) = 1, (5, 3) = 2, (5, 4) = 1, (6, 1) = E, (6, 2) = 7, (6, 3) = 1, (6, 4) = 3})

n:= op([1,1], Data) - 1;

5

City:= Vector(
     n,
     k-> Record(convert(Data[1,..]=~ Data[k+1,..], list)[])
);

City := Vector(5, {(1) = Record(name = A, x = 3, y = 7, pop = 5), (2) = Record(name = B, x = 6, y = 5, pop = 2), (3) = Record(name = C, x = 5, y = 3, pop = 2), (4) = Record(name = D, x = 1, y = 2, pop = 1), (5) = Record(name = E, x = 7, y = 1, pop = 3)})

Dist:= (P1,P2)-> LinearAlgebra:-Norm(P1-P2, 1): #1 is taxi metric.

P:= <x,y>:

Obj:= add(Dist(<City[k]:-x, City[k]:-y>, P)*City[k]:-pop, k= 1..n);   

5*abs(x-3)+5*abs(y-7)+2*abs(x-6)+2*abs(y-5)+2*abs(x-5)+2*abs(y-3)+abs(x-1)+abs(y-2)+3*abs(x-7)+3*abs(y-1)

Procedure to linearize objectives with absolute values:

LinearizeAbsObj:= proc(obj::algebraic, t::name:= :-_t)
local k:= 0, NewCons;
   subsindets(
      obj,
      specfunc(abs),
      proc(ABS)
         k:= k+1;
         NewCons[t[k] >=~ (-1,1)*~op(ABS), t[k] >= 0]:= [][];
         t[k]
      end proc
   ),
   {indices(NewCons, 'nolist')}
end proc:

infolevel[Optimization]:= 2:

CodeTools:-Usage(Optimization:-LPSolve(LinearizeAbsObj(Obj), assume= integer));

LPSolve: calling ILP solver

SolveInteger: number of problem variables 12
SolveInteger: number of general linear constraints 30
memory used=435.90KiB, alloc change=0 bytes, cpu time=16.00ms, real time=11.00ms, gc time=0ns

[51, [x = 5, y = 5, _t[1] = 2, _t[2] = 2, _t[3] = 1, _t[4] = 0, _t[5] = 0, _t[6] = 2, _t[7] = 4, _t[8] = 3, _t[9] = 2, _t[10] = 4]]

 

 


 

Download Taxi_metric_ILP.mw

If A is any real square nonsingular matrix, then A times A-transpose will be symmetric positive definite (i.e., all eigenvalues are positive), which is suitable for Cholesky. The probability that a random matrix is singular is infintesimal, so just take any random real square matrix and muliply it by its transpose. In Maple, the short form for A-transpose is A^+ or A^%T (the former syntax is newer).

A:= LinearAlgebra:-RandomMatrix(6$2):
M:= A.A^+:
L:= LinearAlgebra:-LUDecomposition(M, method= Cholesky);

 

The issue isn't so much that A is nonsquare; it's that any Matrix/Vector/Array operation (not just LinearSolve) that uses option inplace is not allowed to change the size of the container which is supposedly being operated on "in place". So, it fills unused spots with 0. I suppose that a more-logical option might be to use NULL as the fill value, but that wouldn't work if the container were declared sparse.

Addressing your second question: There any many possibilities. Are you looking for an exact solution? Is the system overdetermined (as one would ordinarily expect when rows > columns)? If so, are you looking for a solution in the least-squares sense?

Using matrices/vectors to store the variables Y[i,j] and X[j] makes it easier to enter the objective and the constraints and to display the final results.
 

restart:

p:= 3:

#The demand array, d:
d:= <<2870, 572, 8450, 350, 901, 333, 306, 723, 610> * 1e3>:

n:= rtable_dims(d)[1]:

#The distance matrix:
dist:= Matrix(
   (n$2), shape= symmetric, scan= triangular[upper],
   (r-> [0, r[]])~(
      [[720, 790, 297, 283, 296, 461, 769, 996],
           [884, 555, 722, 461, 685, 245, 1099],
                 [976, 614, 667, 371, 645, 219],
                     [531, 359, 602, 715, 1217],
                           [263, 286, 629, 721],
                                [288, 479, 907],
                                     [448, 589],
                                          [867]
      ]
   )
):

Y:= Matrix((n$2), symbol= y):
X:= Vector(n, symbol= x):
ones:= Matrix((n,1), fill= 1):


#We seek to minimize the objective function, z:
z:= add(dist*~Y.d):


#subject to the constraints:
constraints:= {
   convert(Y.ones =~ 1, set)[],
   add(X) <= p,
   seq(seq(y[i,j] <= x[j], i= n), j= n)
}:

Sol:= Optimization:-LPSolve(z, constraints, assume= binary):

labels:= convert~([$n], symbol):
'z' = Sol[1],
'Y' = DataFrame(eval(Y,Sol[2]), (rows,columns)=~ 'labels'),
'X' = DataSeries(eval(X,Sol[2]), 'labels'= labels);

z = 6.75328*10^8, Y = (Matrix(10, 10, {(1, 1) = ``, (1, 2) = `1`, (1, 3) = `2`, (1, 4) = `3`, (1, 5) = `4`, (1, 6) = `5`, (1, 7) = `6`, (1, 8) = `7`, (1, 9) = `8`, (1, 10) = `9`, (2, 1) = `1`, (2, 2) = 0, (2, 3) = 0, (2, 4) = 0, (2, 5) = 0, (2, 6) = 0, (2, 7) = 1, (2, 8) = 0, (2, 9) = 0, (2, 10) = 0, (3, 1) = `2`, (3, 2) = 0, (3, 3) = 1, (3, 4) = 0, (3, 5) = 0, (3, 6) = 0, (3, 7) = 0, (3, 8) = 0, (3, 9) = 0, (3, 10) = 0, (4, 1) = `3`, (4, 2) = 0, (4, 3) = 0, (4, 4) = 0, (4, 5) = 0, (4, 6) = 0, (4, 7) = 0, (4, 8) = 0, (4, 9) = 0, (4, 10) = 1, (5, 1) = `4`, (5, 2) = 0, (5, 3) = 0, (5, 4) = 0, (5, 5) = 0, (5, 6) = 0, (5, 7) = 1, (5, 8) = 0, (5, 9) = 0, (5, 10) = 0, (6, 1) = `5`, (6, 2) = 0, (6, 3) = 0, (6, 4) = 0, (6, 5) = 0, (6, 6) = 0, (6, 7) = 1, (6, 8) = 0, (6, 9) = 0, (6, 10) = 0, (7, 1) = `6`, (7, 2) = 0, (7, 3) = 0, (7, 4) = 0, (7, 5) = 0, (7, 6) = 0, (7, 7) = 1, (7, 8) = 0, (7, 9) = 0, (7, 10) = 0, (8, 1) = `7`, (8, 2) = 0, (8, 3) = 0, (8, 4) = 0, (8, 5) = 0, (8, 6) = 0, (8, 7) = 1, (8, 8) = 0, (8, 9) = 0, (8, 10) = 0, (9, 1) = `8`, (9, 2) = 0, (9, 3) = 1, (9, 4) = 0, (9, 5) = 0, (9, 6) = 0, (9, 7) = 0, (9, 8) = 0, (9, 9) = 0, (9, 10) = 0, (10, 1) = `9`, (10, 2) = 0, (10, 3) = 0, (10, 4) = 0, (10, 5) = 0, (10, 6) = 0, (10, 7) = 0, (10, 8) = 0, (10, 9) = 0, (10, 10) = 1})), X = (Matrix(9, 2, {(1, 1) = `1`, (1, 2) = 0, (2, 1) = `2`, (2, 2) = 1, (3, 1) = `3`, (3, 2) = 0, (4, 1) = `4`, (4, 2) = 0, (5, 1) = `5`, (5, 2) = 0, (6, 1) = `6`, (6, 2) = 1, (7, 1) = `7`, (7, 2) = 0, (8, 1) = `8`, (8, 2) = 0, (9, 1) = `9`, (9, 2) = 1}))

 


 

Download logistics_ILP.mw

To see the prime factorization in its raw list form, use ifactors instead of ifactor:

ifactors(8650368);

     [1, [[2, 7], [3, 3], [2503, 1]]]

ifactors(8650368)[2];

     [[2, 7], [3, 3], [2503, 1]]

To see that expressed as a product of powers, do

InertForm:-Typeset(`%*`((p-> ``(p[1])^p[2])~(ifactors(8650368)[2])[]));

     (2)^7 * (3)^3 * (2503)

This isn't really a question about Maple because any operating system should have utilities that track and log the usage of any and every program. Any half-way competent sysadmin knows how to access this information . 

Assuming that you're solving an integer linear program (ILP) via Optimization:-LPSolve, you would specify that the variables x[2,3] and x[1,4] (for example) can only take the values 0 or  1 by including the option binaryvariables= {x[2,3], x[1,4]} in the command. See ?LPSolve.

Every time that you have L by itself on the left side of := it changes what L is. So, after your second line, L is no longer an Array, it's a sequence. Here's how to add a new element position:

L:= Array([one, two, three, four, five]):
L(numelems(L)+1):= six:

The spelled out numbers could be anything, and the left side of the second line could be simply L(6).

 

Are you sure that the original had a z-axis label? A basic plot3d command such as

plot3d(x^2+y^2, x= -2..2, y= -2..2);

doesn't produce a z-axis label unless you explicitly include one via, for example,

plot3d(x^2+y^2, x= -2..2, y= -2..2, labels= ['x', 'y', 'z']);

If that doesn't cure your problem, please upload the code that generates the plot.

fsolve returns a sequence of roots (when solving a polynomial) rather than a set of roots, but select expects a set. So, replace fsolve(r, x[2]) with {fsolve(r, x[2])}. When you do that, you're just going to get the empty set on each loop iteration because r has no roots between 0 and 1; indeed, it has no real roots at all. To see the complex roots, use fsolve(r, x[2], complex) without the select.

The code in the attached file runs without error, so I don't know what to correct. Perhaps you simply mean that you want to see the results? For that use

eval(Result_Eva_GB_X3_X2);

after the loop.

The results of code inside loops is ordinarily not shown. That can be adjusted by setting the value of printlevel (see ?printlevel). One needs to be careful with this because it's very easy for the amount of information displayed to become overwhelming, and once it has started displaying there's usually no way to stop it other than killing the whole kernel.

 

solve({coeffs(expand(u-f), x)});

However, you have five variables and only four equations, so you won't get a complete solution.

In the following three function definitions

Ty:= y0-> T*diff((r-> rhs(r[-1]))@pds:-value(T(x, y), x = 0), [1], [y0]); 
Ty2:= y0-> T*diff((r-> rhs(r[-1]))@pds2:-value(T(x, y), x = 0), [1], [y0]); 
Ty3:= y0-> T*diff((r-> rhs(r[-1]))@pds3:-value(T(x, y), x = 0), [1], [y0]);

you need to use numeric differentiation, fdiff, rather than diff (which is only intended for symbolic differentiation). I don't have time to go into the details right now, but it looks like you were using fdiff syntax anyway.

You may also need to reduce the precision of the numeric differentiation for it to return results. Four digits of precision should be enough for any plot. I think that numpoints= 1000 is excessive given the number of mesh points used by pdsolve. You did say spacestep = .25. And I'm not saying that your mesh should be ~1000 points in the space dimension! That would probably take too long to solve.

Also, to ensure that you get multiplication, make sure that you enter "T space bar diff" or T*diff. In the last two of the above three cases, you actually had the single word Tdiff, which is meaningless, and I corrected it. But I'm fairly certain that your attempt to use T as a functional operator like that is incorrect. T and T(x,y) are just symbols; you need to use pds:-value again to access/create a numeric functional operator that corresponds to T.

You can either use

if Equal(Row(A,2), ZeroVector[row](6)) then ....

or (my preference)

if andmap(`=`, A[2, ..], 0) then ....

 

You can localize the value Digits to a particular call to evalf like this:

evalf[1500](Pi);

This avoids the need to explicitly set the value of Digits.

A lot of your computation can be avoided: If x is a float, then op(1, x) is its base-10 integer mantissa. For example, op(1, 3.14) is 314. Integers can be easily split into their digits with convert(..., base, 10). This works for any base if you just change the 10.

Putting it all together, your computation can be reduced to the single line:

Statistics:-Histogram(convert(op(1, evalf[1500](Pi)), base, 10), discrete, thickness= 9);

The appearance of the plot can be improved with some options:

Statistics:-Histogram(
   convert(op(1, evalf[1500](Pi)), base, 10),
   discrete, thickness= 9, view= [-1..10, 0..0.12], axis[1]= [tickmarks= [$0..9]]
);

First 201 202 203 204 205 206 207 Last Page 203 of 395