Error (10028): Can't resolve multiple constant drivers and Error (10029): Constant driver - error-handling

I am new to Verilog, and trying to write a traffic light code where the LED light changes after certain time. I'm keep getting on different errors while compiling. I tried to fix them by changing the arrangement, or variables in the code, but it still fails.
This is the code I wrote,
module traffic_light(clk, reset, G1, Y1, R1, G2, Y2, R2);
input clk, reset;
output reg G1, Y1, R1, G2, Y2, R2;
// parameters for each light control
parameter GREEN = 3'b001,
YELLOW = 3'b010,
RED = 3'b100,
LEFT_GREEN = 3'b101, // assume both red and green will be turned on
LEFT_YELLOW = 3'b110; // assume both red and yellow will be turned on
// finite-state definition (Moore Type):
// ---------------------------
// NSlight EWlight
// ---------------------------
parameter S0 = 3'd0, // GREEN RED
S1 = 3'd1, // YELLOW RED
S2 = 3'd2, // RED, GREEN RED
S3 = 3'd3, // RED, YELLOW RED
S4 = 3'd4, // RED GREEN
S5 = 3'd5, // RED YELLOW
S6 = 3'd6, // RED RED, GREEN
S7 = 3'd7; // RED RED, YELLOW
// internal state variables
reg [2:0] state, next_state;
integer t1 = 19, t2 = 4;
integer count;
// buttons are appropriate for use as clock or reset inputs in a circuit
always #(posedge clk, negedge reset)
if(reset == 'b0) // button pressed, when reset is active low
begin
next_state = S0;
count = t1;
end
else
state <= next_state;
always #(next_state)
begin
next_state = S0;
count = t1;
case(state)
S0:
if (count < 0) // load: if the count reaches below 0, reset
begin
count <= t2;
next_state <= S1;
end
else // enable
begin
// down count
count <= count - 1;
// assign LEDs
G1 <= 1;
Y1 <= 0;
R1 <= 0;
G2 <= 0;
Y2 <= 0;
R2 <= 1;
end
S1:
if (count < 0)
begin
count <= t1;
next_state <= S2;
end
else
begin
G1 <= 0;
Y1 <= 1;
R1 <= 0;
G2 <= 0;
Y2 <= 0;
R2 <= 1;
count <= count - 1;
end
S2:
if (count < 0)
begin
count <= t2;
next_state <= S3;
end
else
begin
G1 <= 1;
Y1 <= 0;
R1 <= 1;
G2 <= 0;
Y2 <= 0;
R2 <= 1;
count <= count - 1;
end
S3:
if (count < 0)
begin
count <= t1;
next_state <= S4;
end
else
begin
G1 <= 0;
Y1 <= 1;
R1 <= 1;
G2 <= 0;
Y2 <= 0;
R2 <= 1;
count <= count - 1;
end
S4:
if (count < 0)
begin
count <= t1;
next_state <= S5;
end
else
begin
G1 <= 0;
Y1 <= 0;
R1 <= 1;
G2 <= 1;
Y2 <= 0;
R2 <= 0;
count <= count - 1;
end
S5:
if (count < 0)
begin
count <= t1;
next_state <= S6;
end
else
begin
G1 <= 0;
Y1 <= 0;
R1 <= 1;
G2 <= 0;
Y2 <= 1;
R2 <= 0;
count <= count - 1;
end
S6:
if (count < 0)
begin
count <= t2;
next_state <= S7;
end
else
begin
G1 <= 0;
Y1 <= 0;
R1 <= 1;
G2 <= 1;
Y2 <= 0;
R2 <= 1;
count <= count - 1;
end
S7:
if (count < 0)
begin
count <= t1;
next_state <= S0;
end
else
begin
G1 <= 0;
Y1 <= 0;
R1 <= 1;
G2 <= 0;
Y2 <= 1;
R2 <= 1;
count <= count - 1;
end
endcase
end
endmodule
and these are the errors generated from the above code:
Error (10028): Can't resolve multiple constant drivers for net "next_state.S0" at traffic_light.v(41)
Error (10029): Constant driver at traffic_light.v(32)
Error (10028): Can't resolve multiple constant drivers for net "next_state.S1" at traffic_light.v(41)
Error (10028): Can't resolve multiple constant drivers for net "next_state.S2" at traffic_light.v(41)
Error (10028): Can't resolve multiple constant drivers for net "next_state.S3" at traffic_light.v(41)
Error (10028): Can't resolve multiple constant drivers for net "next_state.S6" at traffic_light.v(41)
Error (10028): Can't resolve multiple constant drivers for net "next_state.S7" at traffic_light.v(41)
Error (12152): Can't elaborate user hierarchy "traffic_light:inst"
Hope I can get any suggestions or solutions to this problem. Thank you in advance.
I solved the problem after few more searching.
Error (10028): Can't resolve multiple constant drivers for net... VHDL ERROR
"Multiple Constant Drivers" Error Verilog with Quartus Prime
These two links helped solving, the problem is that you cannot assign one variable in two different always block.
The below code is the fixed one.
module traffic_light(clk, reset, G1, Y1, R1, G2, Y2, R2, time_);
input clk, reset;
output reg G1, Y1, R1, G2, Y2, R2;
output reg [4:0] time_; // added, it displays the remaining time
// parameters for each light control
parameter GREEN = 3'b001,
YELLOW = 3'b010,
RED = 3'b100,
LEFT_GREEN = 3'b101, // assume both red and green will be turned on
LEFT_YELLOW = 3'b110; // assume both red and yellow will be turned on
// finite-state definition (Moore Type):
// ---------------------------
// NSlight EWlight
// ---------------------------
parameter S0 = 3'd0, // GREEN RED
S1 = 3'd1, // YELLOW RED
S2 = 3'd2, // RED, GREEN RED
S3 = 3'd3, // RED, YELLOW RED
S4 = 3'd4, // RED GREEN
S5 = 3'd5, // RED YELLOW
S6 = 3'd6, // RED RED, GREEN
S7 = 3'd7; // RED RED, YELLOW
// internal state variables and time settings
reg [2:0] state, next_state;
integer t1 = 19, t2 = 4;
reg count; // changed to count only
always #(posedge clk)
if(reset == 0) // button pressed, when reset is active low
begin
state <= S0;
time_ <= t1;
end
else
begin
state <= next_state;
time_ <= count;
end
always #(*) // changed according to advice in the comment
case(state)
S0: if (count < 0) // load: if the count reaches below 0, reset
begin
count <= t2;
next_state <= S1;
end
else // enable
begin
// down count
count <= count - 1;
// assign LEDs
G1 <= 1;
Y1 <= 0;
R1 <= 0;
G2 <= 0;
Y2 <= 0;
R2 <= 1;
end
S1: if (count < 0)
begin
count <= t1;
next_state <= S2;
end
else
begin
G1 <= 0;
Y1 <= 1;
R1 <= 0;
G2 <= 0;
Y2 <= 0;
R2 <= 1;
count <= count - 1;
end
S2: if (count < 0)
begin
count <= t2;
next_state <= S3;
end
else
begin
G1 <= 1;
Y1 <= 0;
R1 <= 1;
G2 <= 0;
Y2 <= 0;
R2 <= 1;
count <= count - 1;
end
S3: if (count < 0)
begin
count <= t1;
next_state <= S4;
end
else
begin
G1 <= 0;
Y1 <= 1;
R1 <= 1;
G2 <= 0;
Y2 <= 0;
R2 <= 1;
count <= count - 1;
end
S4: if (count < 0)
begin
count <= t2;
next_state <= S5;
end
else
begin
G1 <= 0;
Y1 <= 0;
R1 <= 1;
G2 <= 1;
Y2 <= 0;
R2 <= 0;
count <= count - 1;
end
S5: if (count < 0)
begin
count <= t1;
next_state <= S6;
end
else
begin
G1 <= 0;
Y1 <= 0;
R1 <= 1;
G2 <= 0;
Y2 <= 1;
R2 <= 0;
count <= count - 1;
end
S6: if (count < 0)
begin
count <= t2;
next_state <= S7;
end
else
begin
G1 <= 0;
Y1 <= 0;
R1 <= 1;
G2 <= 1;
Y2 <= 0;
R2 <= 1;
count <= count - 1;
end
S7: if (count < 0)
begin
count <= t1;
next_state <= S0;
end
else
begin
G1 <= 0;
Y1 <= 0;
R1 <= 1;
G2 <= 0;
Y2 <= 1;
R2 <= 1;
count <= count - 1;
end
default:
begin
next_state <= S0;
count <= t1;
end
endcase
endmodule

You have next_state assigned in both processes, and that is causing troubles. We can find it actually described in the Verilog Standard. section 14.5 Driving wired logic
Module path output nets shall not have more than one driver within the module. Therefore, wired logic is not allowed at module path outputs
And it also provides an example:

Related

Rounding series of numbers to get as much "round" numbers as possible and sum up to 100

I have series of numbers that add up to nearly 100 (they are percentages), for example:
A
B
C
49.99
9.99
40.01
And I would like to adjust these to get something like:
A
B
C
50.00
10.00
40.00
Constraints :
The numbers count may vary,
The initial sum can be a little over/under 100 (I use a threshold of 0.1 : if the sum is below 99.9 or over 100.1 then I don't adjust),
sometimes there can be no "nice/round" numbers. In that case I want to distribute the missing/exceeding 1/100s in favor of the lowest numbers like so:
A
B
C
D
E
F
G
33.33
16.66
8.33
8.33
9.99
12.50
10.83
33.33
16.66
8.34
8.34
10.00
12.50
10.83
The function I currently use is working great for distributing the missing/exceeding 1.100s in a loop but does not address the 49.99 → 50.00 problem.
The principle it uses is :
multiply all the % by 100 (to get integers)
assign a "weight" to each integer based on the number of trailing zeroes (so that I adjust preferably the non-round numbers):
30 when (int mod 1000)=0
20 when (int mod 100)=0
10 when (int mod 10)=0
5 when (int mod 5) = 0
else 0.
calculate the missing/exceeding 1/100s for the lowest weight
sort the ints to get the lowest ints first (the sort takes the weight into account)
add/substract 1 to each int until I get a sum of 100.
The resulting function will be written in Postgres' Pl/PgSql but I'm mostly interested in knowing if such algorithms exist and how they are named (of course, a link to a working function would be very much appreciated).
I ended up splitting the problem in 2 :
adjust the original shares to get "nicer" numbers (49.99 → 50.00) and
add a few 1/100s here and there to obtain a 100% total.
The result is satisfying, I even integrated a few special values for common fractions (200/3, 100/3, 100/6, 100/12...) so that 3x33.33 don't end up with 33.35, 33.35 and 33.30, less "nice/round" but more fair. Note there is only one loop for the final adjustments. Performance is acceptable : 3.5 sec for 100000 rows.
The following SO question and the included Wikipedia article helped me understand the possible biases and their pros/cons.
Here is the code for those interested :
CREATE OR REPLACE FUNCTION public.normalizeshares_weight(share INT) RETURNS INT AS
$BODY$
SELECT CASE
WHEN share % 10000 = 0 THEN 40
WHEN share % 1000 = 0 THEN 30
WHEN share % 100 = 0 THEN 20
WHEN share % 50 = 0 OR (share = ANY('{6666,3333,1666,833,416}')) THEN 15
WHEN (share % 10 = 0) THEN 10
WHEN share % 5 = 0 THEN 5
ELSE 0 END;
$BODY$ LANGUAGE SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION public.normalizeshares(shares NUMERIC[]) RETURNS NUMERIC(5,2)[] AS
$BODY$
DECLARE
intshares INT[];
adjshares INT[];
weight INT[];
result NUMERIC[];
nb0 INT = 0;
nb5 INT = 0;
nb10 INT = 0;
nb15 INT = 0;
nb20 INT = 0;
nb30 INT = 0;
nb40 INT = 0;
initot INT = 0;
tot INT = 0;
nb INT = 0;
w INT = 0;
diff INT;
each INT;
bestweight INT;
BEGIN
FOR i IN 1..ARRAY_LENGTH(shares,1) LOOP
intshares[i] := FLOOR(COALESCE(shares[i],0)*100);
weight[i] := normalizeshares_weight(intshares[i]);
bestweight := weight[i];
adjshares[i] := intshares[i];
IF normalizeshares_weight(intshares[i]+1) > bestweight THEN adjshares[i] := intshares[i]+1; bestweight := normalizeshares_weight(intshares[i]+1); END IF;
IF normalizeshares_weight(intshares[i]+2) > bestweight THEN adjshares[i] := intshares[i]+2; bestweight := normalizeshares_weight(intshares[i]+2); END IF;
IF normalizeshares_weight(intshares[i]+3) > bestweight THEN adjshares[i] := intshares[i]+2; bestweight := normalizeshares_weight(intshares[i]+3); END IF;
IF normalizeshares_weight(intshares[i]-1) > bestweight THEN adjshares[i] := intshares[i]-1; bestweight := normalizeshares_weight(intshares[i]-1); END IF;
IF normalizeshares_weight(intshares[i]-2) > bestweight THEN adjshares[i] := intshares[i]-2; bestweight := normalizeshares_weight(intshares[i]-2); END IF;
IF normalizeshares_weight(intshares[i]-3) > bestweight THEN adjshares[i] := intshares[i]-2; bestweight := normalizeshares_weight(intshares[i]-3); END IF;
tot := tot + adjshares[i];
initot := initot + intshares[i];
weight[i] := bestweight; -- normalizeshares_weight(adjshares[i]); already calculated
IF weight[i]=0 THEN nb0 := nb0 + 1;
ELSIF weight[i]=5 THEN nb5 := nb5 + 1;
ELSIF weight[i]=10 THEN nb10 := nb10 + 1;
ELSIF weight[i]=15 THEN nb15 := nb15 + 1;
ELSIF weight[i]=20 THEN nb20 := nb20 + 1;
ELSIF weight[i]=30 THEN nb30 := nb30 + 1;
ELSIF weight[i]=40 THEN nb40 := nb40 + 1;
END IF;
result[i] := (intshares[i]::NUMERIC / 100)::NUMERIC(5,2);
END LOOP;
IF tot=10000 THEN
-- RAISE NOTICE 'adjtot=100.00 : %',adjshares::numeric[];
FOR i IN 1..ARRAY_LENGTH(shares,1) LOOP
result[i] := (adjshares[i]::NUMERIC / 100)::NUMERIC(5,2);
END LOOP;
ELSIF (initot=10000) OR (ABS(10000-tot)>90) THEN
-- RAISE NOTICE 'No adj needed, initot=%, tot=%',initot,tot;
ELSE
IF nb0 > 0 THEN nb := nb0; w := 0;
ELSIF nb5 > 0 THEN nb := nb5; w := 5;
ELSIF nb10 > 0 THEN nb := nb10; w := 10;
ELSIF nb15 > 0 THEN nb := nb15; w := 15;
ELSIF nb20 > 0 THEN nb := nb20; w := 20;
ELSIF nb30 > 0 THEN nb := nb30; w := 30;
ELSIF nb40 > 0 THEN nb := nb40; w := 40;
END IF;
diff := 10000 - tot;
each := diff/nb+diff/abs(diff);
-- RAISE NOTICE 'nb=%, w=%, diff=%, tot=%, adj=%',nb,w,diff,tot,adjshares::numeric[];
FOR i IN 1..ARRAY_LENGTH(shares,1) LOOP
IF weight[i]=w THEN
IF diff=0 THEN
ELSIF nb=1 THEN
adjshares[i] := adjshares[i] + diff;
ELSIF nb>1 THEN
adjshares[i] := adjshares[i] + each;
diff := diff - each;
END IF;
nb := nb -1;
END IF;
result[i] := (adjshares[i]::NUMERIC / 100)::NUMERIC(5,2);
END LOOP;
END IF;
RETURN result;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
And a few results :
% select normalizeshares('{49.99,9.99,40.01}');
normalizeshares
---------------------
{50.00,10.00,40.00}
% select normalizeshares('{33.33,16.66,8.33,8.33,9.99,12.5,10.83}');
normalizeshares
-------------------------------------------
{33.33,16.66,8.33,8.33,10.00,12.50,10.85}

How to derive a Fixed Length Output signal from a variable length Input signal in verilog

I have an HDL Block in which the output follows the input in such a way that when input signal is binary 0, output remains 0 but when input turns 1, output turns 1 for a preset number of clock cycles (signal_length). i.e. input may remain high for suppose 65 or 66 clock cycles but output should remain high for preset number of clock cycles. I tried to accomplish the task with Verilog. But I am having an error and I don’t know how to rectify. Hope someone can help.
module last_ind
#(
parameter MAX_LENGTH = 262144,
parameter signal_length
)
(
input clk,
input [17:0] pkt_length,
input tdata,
output tlast
);
reg [17:0] cnt = 0;
always # (posedge clk)
begin
if ((tdata==1) && (cnt<signal_length))
tlast <= 1;
else
cnt <= 0;
end
assign cnt <= cnt + 1'b1;
endmodule
maybe something like this will do. It should keep the signal up for the signal_length cycles and will reset when tdata gets '0'. You decide on the correct protocol though.
reg [17:0] cnt = signal_length;
always # (posedge clk) begin
if (cnt < signal_lenth)
cnt <= cnt + 1;
else if (cnt == signal_length + 1 && tdata == 1 && tlast == 0) begin
cnt <= 0;
tlast <= 1;
end
else if (tdata == 0) begin
cnt <= sighal_length + 1;
tlast <= 0;
end
else
tlast <= 0;
end

VHDL Syntax error in user defined package RNG for genetic algorithm in line number 5

Library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Type arr is array (1 to mut_bits) of integer;
type chrom_matrix is array (1 to pop_size) of std_logic_vector(1 to n_comp);
type fitness_arr is array (1 to pop_size) of integer range 0 to 1000;
--type fitness_arr1 is array(1 to pop_size) of real;
type adj_matrix is array (1 to n_comp,1 to n_comp) of bit;
function evalfnc (signal chromosome: in std_logic_vector(1 to 8); signal cut_info:adj_matrix) return integer;
procedure randg (variable x,y,t:in integer range 0 to 1000; variable z: out integer);
procedure convert_bit(variable a:in integer;variable y:out std_logic_vector(8 downto 1));
end rng;
package body rng is
procedure randg (variable x,y,t:in integer range 0 to 1000; variable z: out integer) is
variable val, a:integer range 0 to 1000:= 0;
begin
if x>y then
a:= x-y;
else
a:= y-x;
end if;
if t > 3*a then
val:= (t-a)/2;
elsif t > a then
val:= t-a;
else
val:= (x+y+t)/2;
end if;
z:= val;
end randg;
function evalfnc (signal chromosome: in std_logic_vector(1 to 8); signal cut_info:adj_matrix) return integer is
variable fitness: integer range 0 to 500:= 0;
variable cut_val: integer range 0 to 15:= 0;
variable max_fit:integer range 0 to 360:=100;
begin
for i in 1 to n_comp loop
for j in 1 to n_comp loop
if cut_info(i,j)= ‘1’ then
cut_val:= cut_val +1;
end if;
end loop;
end loop;
fitness := max_fit - cut_val;
return fitness;
end evalfnc;
procedure convert_bit(variable a:in integer ; variable y:out std_logic_vector(8 downto 1)) is
variable no:std_logic_vector(8 downto 1):=”00000000”;
variable num: integer range 0 to 256;
begin
num:= a;
if num <= 255 and num>= 128 then
no(8):=’1’;
num:=num - 128;
end if;
if num < 128 and num >= 64 then
no(7):=’1’;
num:=num - 64;
end if;
if num < 64 and num >= 32 then
no(6):=’1’;
num:=num −32;
end if;
if num < 32 and num >= 16 then
no(5):=’1’;
num:=num - 16;
end if;
if num < 16 and num >= 8 then
no(4):=’1’;
num:=num - 8;
end if;
if num < 8 and num >= 4 then
no(3):=’1’;
num:=num - 4;
end if;
if num < 4 and num >= 2 then
no(2):=’1’;
num:=num - 2;
end if;
if num < 2 then
no(1):=’1’;
end if;
y:= no;
end convert_bit;
end rng;
Line 5 should read package rng is.

Verilog: Sum over n register

Im trying to build an moving average module. It should use the number of values to use as parameter.
How do I get the sum of all n tmp-registers using a for- or gernerate-block within one clock-cylce?
reg [WORDLEN - 1:0] tmp [SIZE - 1:0];
reg [WORDLEN + SIZE / 2 - 1:0] sum;
always #(posedge clk)
sum <= sum(tmp) // Like <= tmp[0] + tmp[1] + ... + tmp[SIZE-1]
Loops like this tend to be easier to understand if you first break apart the synchronous and combinatorial parts. First we have a combinatorial loop which unrolls to a configurable number of adds. Then imply a flip-flop on the result.
integer i;
reg [WORDLEN + SIZE / 2 - 1:0] sum_comb;
always #* begin
sum_comb = 'd0;
for( i=0; i< SIZE; i=i+1) begin
sum_comb = sum_comb + tmp[i];
end
end
always #(posedge clk) begin
sum <= sum_comb;
end
If you use SystemVerilog, you can just write:
always #(posedge clk)
sum <= tmp.sum;
Below is a complete sample code:
module test;
parameter WORDLEN = 8;
parameter SIZE = 4;
reg [WORDLEN - 1:0] tmp [SIZE - 1:0];
reg [WORDLEN + SIZE / 2 - 1:0] sum;
logic clk = 0;
initial begin
tmp = '{ '{1}, '{4}, '{6}, '{7}};
forever begin
clk = ~clk;
#10;
tmp [0] = tmp[0] + 1; //Increment tmp[0] twice during each clock for testing
end
end
always #(posedge clk) begin
sum <= tmp.sum ;
$display ("sum(tmp) = sum(%p) = %d", tmp, sum) ;
end
endmodule
output:
# sum(tmp) = sum('{1, 4, 6, 7}) = 18
# sum(tmp) = sum('{1, 4, 6, 9}) = 20
# sum(tmp) = sum('{1, 4, 6, 11}) = 22
# sum(tmp) = sum('{1, 4, 6, 13}) = 24
# sum(tmp) = sum('{1, 4, 6, 15}) = 26
# sum(tmp) = sum('{1, 4, 6, 17}) = 28

Proc Optmodel Conditional Constraint SAS

I'm fairly new to proc optmodel and having trouble sorting out some syntax.
Here is my dataset.
data opt_test;
input ID GRP $ x1 MIN MAX y z;
cards;
2 F 10 9 11 1.5 100
3 F 10 9 11 1.2 50
4 F 11 9 11 .9 20
8 G 5 4 6 1.2 300
9 G 6 4 6 .9 200
1 H 21 18 22 1.2 300
7 H 20 18 22 .8 1000
;
run;
There are a few things going on here:
The IDs within a GRP must have the same x2, which is constrained by MIN and MAX. I now wish to further constrain the increase/decrease of x2 based on the value of y. If y<1, I do not want x2 to go below .95*x1. If y>1, I do not want x2 to exceed 1.05*x1. I've looked online and tried a few things to make this happen. Here is my latest attempt, cond_1 and cond_2 are the problems of interest, as everything else works:
proc optmodel;
set<num> ID;
string GRP{ID};
set GRPS = setof{i in ID} GRP[i];
set IDperGRP{gi in GRPS} = {i in ID: GRP[i] = gi};
number x1{ID};
number MIN{ID};
number MAX{ID};
var x2{gi in GRPS} >= max{i in IDperGRP[gi]} MIN[i]
<= min{i in IDperGRP[gi]} MAX[i]
;
impvar x2byID{i in ID} = x2[GRP[i]];
number y{ID};
number z{ID};
read data opt_test into
ID=[ID]
GRP
x1
MIN
MAX
y
z
;
max maximize = sum{gi in GRPS} sum{i in IDperGRP[gi]}
(x2[gi]) * (1-(x2[gi]-x1[i])*y[i]/x1[i]) * z[i];
con cond_1 {i in ID}: x2[i] >=
if y[i]<1 then .95*x1[i] else 0;
con cond_2 {i in ID}: x2[i] <=
if y[i]>=1 then 1.05*x1[i] else 99999999;
solve;
create data results from [ID]={ID} x2=x2byID GRP x1 MIN MAX y z;
print x2 maximize;
quit;
I would calculate the global max and min in a data step outside of PROC OPTMODEL and then set the values. Like so:
data opt_test;
set opt_test;
if y < 1 then
min2 = .95*x1;
else
min2 = 0;
if y>=1 then
max2 = 1.05*x1;
else
max2 = 9999999999;
Min_old = min;
max_old = max;
MIN = max(min,min2);
MAX = min(max,max2);
run;
But you have a problem with group G. Use expand to see it.
proc optmodel;
set<num> ID;
string GRP{ID};
set GRPS = setof{i in ID} GRP[i];
set IDperGRP{gi in GRPS} = {i in ID: GRP[i] = gi};
number x1{ID};
number MIN{ID};
number MAX{ID};
var x2{gi in GRPS} >= max{i in IDperGRP[gi]} MIN[i]
<= min{i in IDperGRP[gi]} MAX[i]
;
impvar x2byID{i in ID} = x2[GRP[i]];
number y{ID};
number z{ID};
read data opt_test into
ID=[ID]
GRP
x1
MIN
MAX
y
z
;
max maximize = sum{gi in GRPS} sum{i in IDperGRP[gi]}
(x2[gi]) * (1-(x2[gi]-x1[i])*y[i]/x1[i]) * z[i];
/*con cond_1 {i in ID}: x2[i] >=
if y[i]<1 then .95*x1[i] else 0;
con cond_2 {i in ID}: x2[i] <=
if y[i]>=1 then 1.05*x1[i] else 99999999;*/
expand;
solve;
create data results from [ID]={ID} x2=x2byID GRP x1 MIN MAX y z;
print x2 maximize;
quit;
You will see that X2[G] is infeasible:
Var x2[G] >= 5.7 <= 5.25
X2[G] starts in [4,6];
For ID=8, X=5 and Y=1.2. By your logic, this sets the max to 5.25 (5*1.2).
Now X2[G] in [4,5.25]
For ID=9, X=6 and Y=0.9. By your logic this sets the min to 5.7 (0.95*6).
X2[G] in [5.7,5.25] <-- BAD!
The biggest problem with the model in the question is that the indexing of the var x2 is incorrect. You could fix that by referring to the group of the ID as such:
con cond_1 {i in ID}: x2[GRP[i]] >=
if y[i] < 1 then .95*x1[i] else 0;
con cond_2 {i in ID}: x2[GRP[i]] <=
if y[i]>=1 then 1.05*x1[i] else 99999999;
but a description of the constraint that reads closer to the business problem is to put a filter in the constraint definition itself:
con Cond_1v2 {i in ID: y[i] < 1} : x2[GRP[i]] >= .95 * x1[i];
con Cond_2v2 {i in ID: Y[i] >= 1}: x2[GRP[i]] <= 1.05 * x1[i];
In either case, the problem becomes infeasible because of the constraint Cond2v2, as you can see using expand (as #DomPazz pointed out), and in particular the expand / iis option, which will print the conflicting constraints when it can determine them:
solve with nlp / iis=on;
expand / iis;