Currying a function with a variable in J - currying

I can create a function that multiplies by 2 with 2&\*, and indeed 20 = (2&\*)10
What I want to do is create a factory-function that makes these to order.
So, I want a monad f s.t. ( f y ) x == (y * x )
whilst (\*& 2) 3 works ((\*&) 2) 3 doesn't, so trying explicitly:
(3 : 'y&*') 2 produces a syntax error.
Where am I going wrong ?

A verb that creates a verb is actually an adverb1 in J:
f =: 1 : 'm&*'
2 f
2&*
(2 f) 5
10
(i.10)f 5
0 5 10 15 20 25 30 35 40 45
or tacitly:
f =: &*
2 f
2&*
h =: 3 :'...' won't work because that produces a verb and then h y wants to be a noun.
g =: 4 :'x&* y' is fine and equivalent to f.
[1]: or a conjunction

Related

consecutive days constraint in linear programming

For a work shift optimization problem, I've defined a binary variable in PuLP as follows:
pulp.LpVariable.dicts('VAR', (range(D), range(N), range(T)), 0, 1, 'Binary')
where
D = # days in each schedule we create (=28, or 4 weeks)
N = # of workers
T = types of work shift (=6)
For the 5th and 6th type of work shift (with index 4 and 5), I need to add a constraint that any worker who works these shifts must do so for seven consecutive days... and not any seven days but the seven days starting from Monday (aka a full week). I've tried defining the constraint as follows, but I'm getting an infeasible solution when I add this constraint and try to solve the problem (it worked before without it)
I know this constraint (along with the others from before) should theoretically be feasible because we manually schedule work shifts with the same set of constraints. Is there anything wrong with the way I've coded the constraint?
## looping over each worker
for j in range(N):
## looping for every Monday in the 28 days
for i in range(0,D,7):
c = None
## accessing only the 5th and 6th work shift type
for k in range(4,T):
c+=var[i][j][k]+var[i+1][j][k]+var[i+2][j][k]+var[i+3][j][k]+var[i+4][j][k]+var[i+5][j][k]+var[i+6][j][k]
problem+= c==7
If I understand correctly then your constraint requires that each worker is required to work the 4th and 5th shift in every week. This is because of c == 7, i.e. 7 of the binaries in c must be set to 1. This does not allow any worker to work in shift 0 through 3, right?
You need to change the constraint so that c == 7 is only enforced if the worker works any shift in that range. A very simple way to do that would be something like
v = list()
for k in range(4,T):
v.extend([var[i][j][k], var[i+1][j][k], var[i+2][j][k], var[i+3][j][k], var[i+4][j][k], var[i+5][j][k], var[i+6][j][k]])
c = sum(v)
problem += c <= 7 # we can pick at most 7 variables from v
for x in v:
problem += 7 * x <= c # if any variable in v is picked, then we must pick 7 of them
This is by no means the best way to model that (indicator variables would be much better), but it should give you an idea what to do.
Just to offer an alternative approach, assuming (as I read it) that for any given week a worker can either work some combination of shifts in [0:3] across the seven days, or one of the shifts [4:5] every day: we can do this by defining a new binary variable Y[w][n][t] which is 1 if in week w worker n does a restricted shift t, 0 otherwise. Then we can relate this variable to our existing variable X by adding constraints so that the values X can take depend on the values of Y.
# Define the sets of shifts
non_restricted_shifts = [0,1,2,3]
restricted_shifts = [4,5]
# Define a binary variable Y, 1 if for week w worker n works restricted shift t
Y = LpVariable.dicts('Y', (range(round(D/7)), range(N), restricted_shifts), cat=LpBinary)
# If sum(Y[week][n][:]) = 1, the total number of non-restricted shifts for that week and n must be 0
for week in range(round(D/7)):
for n in range(N):
prob += lpSum(X[d][n][t] for d in range(week*7, week*7 + 7) for t in non_restricted_shifts) <= 1000*(1-lpSum(Y[week][n][t] for t in restricted_shifts))
# If worker n has 7 restricted shift t in week w, then Y[week][n][t] == 1, otherwise it is 0
for week in range(round(D/7)):
for n in range(N):
for t in restricted_shifts:
prob += lpSum(X[d][n][t] for d in range(week*7, week*7+7)) <= 7*(Y[week][n][t])
prob += lpSum(X[d][n][t] for d in range(week*7, week*7+7)) >= Y[week][n][t]*7
Some example output (D=14, N=2, T=6):
/ M T W T F S S / M T W T F S S / M T W T F S S / M T W T F S S
WORKER 0
Shifts: / 2 3 1 3 3 2 2 / 1 0 2 3 2 2 0 / 3 1 2 2 3 1 1 / 2 3 0 3 3 0 3
WORKER 1
Shifts: / 3 1 2 3 1 1 2 / 3 3 2 3 3 3 3 / 4 4 4 4 4 4 4 / 1 3 2 2 3 2 1
WORKER 2
Shifts: / 1 2 3 1 3 1 1 / 3 3 2 2 3 2 3 / 3 2 3 0 3 1 0 / 4 4 4 4 4 4 4
WORKER 3
Shifts: / 2 2 3 2 1 2 3 / 5 5 5 5 5 5 5 / 3 1 3 1 0 3 1 / 2 2 2 2 3 0 3
WORKER 4
Shifts: / 5 5 5 5 5 5 5 / 3 3 1 0 2 3 3 / 0 3 3 3 3 0 2 / 3 3 3 2 3 2 3

Concatenating csv files side by side in pandas [duplicate]

This question already has answers here:
How to merge two dataframes side-by-side?
(6 answers)
Closed 2 years ago.
I have 6 csv files like this:
A,5601093669
C,714840722
D,3311821086
E,3714631762
F,2359322409
G,4449445373
H,1321142307
I,3403144346
K,2941319082
L,5982421765
M,1431041943
N,2289666237
P,2944809622
Q,2266749163
R,3503618053
S,3995185703
T,3348978524
V,4184646229
W,790817778
Y,1747887712
And I would like to concatenate them side by side, ie:
A,5601093669,5601093669,5601093669,5601093669...
C,714840722,714840722,714840722,714840722 ...
D,3311821086,3311821086,3311821086,3311821086...
Or even make a data frame directly like this:
Letters Counts1 Counts2 Counts3 ...
0 A 949038913 949038913 949038913 ...
1 C 154135114 154135114 154135114 ...
.
.
.
I tried to use pandas, but I only concatenate them one over the other like this:
Letters Counts
0 A 949038913
1 C 154135114
2 D 602309784
3 E 672070230
4 F 430604264
5 G 760092523
6 H 242152981
7 I 608218717
8 K 558412515
9 L 1057894498
10 N 455966669
11 M 238551663
12 P 554657856
13 Q 423767129
14 R 650581191
15 S 819127381
16 T 632469374
17 V 717790671
18 W 144439568
19 Y 324996779
20 A 5601093669
21 C 714840722
22 D 3311821086
23 E 3714631762
24 F 2359322409
25 G 4449445373
26 H 1321142307
27 I 3403144346
28 K 2941319082
29 L 5982421765
30 M 1431041943
31 N 2289666237
the code was like this:
extension = 'csv'
all_filenames = [i for i in glob.glob('*.{}'.format(extension))]
df_from_each_file = [pd.read_csv(f, header=None, names=['Latters', 'Counts'])
for f in all_filenames]
frame = pd.concat(df_from_each_file, axis=0, ignore_index=True)
Any tip or improvement would be very welcome!
Thank you by your time!
Paulo
use axis=1 in pd.concat function
you can refer https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html

Why I do not get the right answer

I think logically the following code is right but I get the wrong answer:
.mod file:
set R := {1,2};
set D1 := {1,2,4,5};
set P1 := {1,2,3,4,5};
var V{D1,R}, binary;
param Ud{D1,R} ;
param U{P1,R} ;
minimize obj{p in D1, r in R}: V[p,r] * (Ud[p,r]+ sum{j in P1: j!=p} U[j,r]);
s.t. a10{ r in R }: sum{p in D1} V[p,r]=2 ;
.dat file:
param Ud: 1 2:=
1 -10 -6
2 -20 -4
4 1 -10
5 -4 -4;
param U: 1 2 :=
1 -8.1 -3
2 -6.8 -8
3 -7.2 1
4 -16 -4
5 -6.8 -4;
Basically for each r and for two p , I want to minimize (Ud[p,r] + sum{j in P: j!=p} U[j,r])
But it always give me V[1,r]=v[5,r]=1 even if V[2,r] minimize obj function.
I except to get V[2,r]=1 because -20 + (-8.1-7.2 -16-6.8) is the most negative.
Your syntax for the objective function is incorrect; it should be
minimize obj: sum {p in D1, r in R} V[p,r] * (Ud[p,r]+ sum{j in P1: j != p} U[j,r]);
(Note the location of the colon (:), and the presence of the sum.) To be honest I'm not exactly sure what AMPL was doing in response to your objective function, but I would just treat the results as unpredictable.
With the revised objective function, the optimal solution is:
ampl: display V;
V :=
1 1 1
1 2 1
2 1 1
2 2 0
4 1 0
4 2 1
5 1 0
5 2 0
;

Efficiently assigning values to multidimensional array based on indices list on one dimension

I have a matrix M of size [S1, S2, S3].
I have another matrix K that serves as the indices in the first dimension that I want to assign, with size [1, S2, S3].
And V is a [1, S2, S3] matrix which contains the values to be assigned correspondingly.
With for loops, this is how I did it:
for x2 = 1:S2
for x3 = 1:S3
M(K(1,x2,x3), x2, x3) = V(1, x2, x3)
endfor % x3
endfor % x2
Is there a more efficient way to do this?
Visualization for 2D case:
M =
1 4 7 10
2 5 8 11
3 6 9 12
K =
2 1 3 2
V =
50 80 70 60
Desired =
1 80 7 10
50 5 8 60
3 6 70 12
Test case:
M = reshape(1:24, [3,4,2])
K = reshape([2,1,3,2,3,3,1,2], [1,4,2])
V = reshape(10:10:80, [1,4,2])
s = size(M)
M = assign_values(M, K, V)
M =
ans(:,:,1) =
1 20 7 10
10 5 8 40
3 6 30 12
ans(:,:,2) =
13 16 70 22
14 17 20 80
50 60 21 24
I'm looking for an efficient way to implement assign_values there.
Running Gelliant's answer somehow gives me this:
key = sub2ind(s, K, [1:s(2)])
error: sub2ind: all subscripts must be of the same size
You can use sub2ind to use your individual subscripts to linear indices. These can then be used to replace them with the values in V.
M = [1 4 7 10 ;...
2 5 8 11 ;...
3 6 9 12];
s=size(M);
K = [2 1 3 2];
K = sub2ind(s,K,[1:s(2)])
V = [50 80 70 60];
M(K)=V;
You don't need reshape and M=M(:) for it to work in Matlab.
I found that this works:
K = K(:)'+(S1*(0:numel(K)-1));
M(K) = V;
Perhaps this is supposed to work the same way as Gelliant's answer, but I couldn't make his answer work, somehow =/

How can I run a vlookup function in SQL within the same table?

I'm fairly new to SQL and struggling to find a good way to run the following query.
I have a table that looks something like this:
NAME JOB GRADE MANAGER NAME
X 7 O
Y 6 X
Z 5 X
A 4 Z
B 3 Z
C 2 Z
In this table, it shows that Y and Z report into X, and A, B and C report into Z.
I want to create a computed column showing the grade each person's most senior direct report or "n/a" if they don't manage anyone. So that would look something like this:
NAME JOB GRADE MANAGER NAME GRADE OF MOST SENIOR REPORT
X 7 O 6
Y 6 X N/A
Z 5 X 4
A 4 Z N/A
B 3 Z N/A
C 2 Z N/A
How would I do this?
SELECT g.*,isnull(convert(nvarchar, (SELECT max(g2.GRADE)
FROM dbo.Grade g2 WHERE
g2.manager =g.NAME AND g2.NAME!=g.NAME )),'N/A') as most_graded
FROM dbo.Grade g
The max will find out the topmost graded
Input
X 7 O
y 6 X
Z 5 X
A 6 Z
C 2 Z
Output
X 7 O 6
y 6 X N/A
Z 5 X 6
A 6 Z N/A
C 2 Z N/A
Something like this:
select name, job_grade, manager_name,
(select max(job_grade) from grades g2
where g2.manager_name = g1.name) as grade_of_most_recent_senior
from grades g1
order by name;
The above is ANSI SQL and should work on any DBMS.
SQLFiddle example: http://sqlfiddle.com/#!15/e0806/1