Calling the superclass constructor 'rl.env.MATLABEnvironment' after an object use or after a return statement is not supported.
4 次查看(过去 30 天)
显示 更早的评论
We aim to maximize the sum rate through the joint optimization of power allocation, UAV mobilty, and SIC decoding order for a UAV-NOMA system using reinforcement learning DDPG optimization. The following errors arise in the learning environment, please can anyone rectify and stabilize the learning environment: 'Calling the superclass constructor 'rl.env.MATLABEnvironment' after an object use or after a return statement is not supported'. I attached the learning environment script: classdef NOMAEnv < rl.env.MATLABEnvironment
properties
% System parameters
numSubchannels = 6;
P_max = 20; % Maximum power (watts)
N_max = 5; % Number of mobile NOMA users
timeSteps = 10; % Number of time steps
uavSpeed = 5; % UAV speed (m/s)
flightHeight = 100; % UAV flight height (meters)
radius = 100; % Area radius (meters)
% Additional properties
userPositions;
currentStep;
T = 100; % Total duration
delta_t; % Duration of each time slot
% Optimal solutions (for comparison)
optimalPowerAllocation;
optimalTrajectory;
optimalDecodingOrder;
optimalSumRate;
end
properties(Access = protected)
State;
IsDone = false;
end
methods
function this = NOMAEnv()
% Load optimal solutions
load('Training_data.mat', 'optimalPowerAllocation', 'optimalTrajectory', 'optimalDecodingOrder', 'optimalSumRate');
this.optimalPowerAllocation = optimalPowerAllocation;
this.optimalTrajectory = optimalTrajectory;
this.optimalDecodingOrder = optimalDecodingOrder;
this.optimalSumRate = optimalSumRate;
this.delta_t = this.T / this.timeSteps;
% Initialize Observation and Action info
ObservationInfo = rlNumericSpec([3 * this.N_max + 3, 1]);
ObservationInfo.Name = 'User distances, angles, current UAV position, and time step';
ObservationInfo.LowerLimit = [-inf * ones(2 * this.N_max, 1); zeros(this.N_max, 1); -this.radius * ones(2, 1); 0; 0];
ObservationInfo.UpperLimit = [inf * ones(2 * this.N_max, 1); ones(this.N_max, 1); this.radius * ones(2, 1); this.flightHeight; this.timeSteps];
ActionInfo = rlNumericSpec([this.N_max + 2, 1], 'LowerLimit', -1, 'UpperLimit', 1);
ActionInfo.Name = 'Actions for power allocation, UAV movement, SIC order';
% Call superclass constructor
this@rl.env.MATLABEnvironment(ObservationInfo, ActionInfo);
% Initialize environment
this.reset();
end
function [Observation, Reward, IsDone, LoggedSignals] = step(this, Action)
LoggedSignals = [];
% Update power allocation, UAV position, and decoding order based on the action
[powerAllocation, uavPosition, decodingOrder] = this.interpretAction(Action);
% Update environment state
this.updateState(uavPosition, decodingOrder);
% Calculate reward (sum rate)
Reward = this.calculateSumRate(powerAllocation, uavPosition, decodingOrder);
% Check if episode is done
this.currentStep = this.currentStep + 1;
if this.currentStep >= this.timeSteps
this.IsDone = true;
end
IsDone = this.IsDone;
Observation = this.State;
end
function InitialObservation = reset(this)
% Initialize user positions
this.userPositions = rand(this.N_max, 2) * 2 * this.radius - this.radius;
% Initialize UAV position
uavInitialPosition = [0, 0, this.flightHeight];
% Initialize decoding order
initialDecodingOrder = randperm(this.N_max);
% Reset current step
this.currentStep = 0;
% Update state
this.updateState(uavInitialPosition, initialDecodingOrder);
InitialObservation = this.State;
this.IsDone = false;
end
end
methods (Access = protected)
function updateState(this, uavPosition, decodingOrder)
% Calculate distances and angles to users
relativePositions = this.userPositions - uavPosition(1:2);
distances = vecnorm(relativePositions, 2, 2);
angles = atan2(relativePositions(:, 2), relativePositions(:, 1));
this.State = [distances; angles; decodingOrder / this.N_max; uavPosition'; this.currentStep];
end
function [powerAllocation, uavPosition, decodingOrder] = interpretAction(this, Action)
% Extract power allocation (first N_max elements)
powerAllocation = (Action(1:this.N_max) + 1) / 2 * this.P_max / this.N_max;
% Extract UAV movement (next 2 elements)
uavMovement = Action(this.N_max+1:this.N_max+2) * this.uavSpeed * this.delta_t;
currentUAVPosition = this.State(end-3:end-1);
uavPosition = currentUAVPosition + [uavMovement; 0];
uavPosition(3) = this.flightHeight; % Maintain constant height
% Decode SIC order (remaining elements, if any)
decodingOrderAction = Action(this.N_max+3:end);
[~, decodingOrder] = sort(decodingOrderAction);
end
function sumRate = calculateSumRate(this, powerAllocation, uavPosition, decodingOrder)
% Implement your sum rate calculation here
% This is a placeholder implementation
distances = vecnorm(this.userPositions - uavPosition(1:2), 2, 2);
channelGains = 1 ./ (1 + distances).^2; % Simplified channel model
sumRate = sum(log2(1 + powerAllocation(decodingOrder) .* channelGains(decodingOrder)));
end
end
end
0 个评论
采纳的回答
Steven Lord
2024-6-18
In the Guidelines for Constructors section on this documentation page, one of the guidelines is "If your constructor makes an explicit call to a superclass constructor, this call must occur before any other reference to the constructed object and cannot occur after a return statement."
Your code violates this guideline; you call the superclass constructor after assigning values to the constructed object's properties. Move the "this.<property>" assignments to after you call the superclass constructor.
4 个评论
Steven Lord
2024-6-18
Let's look at the constructor up to and including the superclass constructor.
function this = NOMAEnv()
% Initialize Observation and Action info
ObservationInfo = rlNumericSpec([2 * this.N_max + 2 * this.numSubchannels + 3, 1]);
ObservationInfo.Name = 'User distances, angles, current UAV position, time step, and subchannel states';
ObservationInfo.LowerLimit = [-inf * ones(2 * this.N_max, 1); zeros(this.numSubchannels, 1); -this.radius * ones(2, 1); 0; 0];
ObservationInfo.UpperLimit = [inf * ones(2 * this.N_max, 1); ones(this.numSubchannels, 1); this.radius * ones(2, 1); this.flightHeight; this.timeSteps];
ActionInfo = rlNumericSpec([this.N_max + this.numSubchannels + 2, 1], 'LowerLimit', -1, 'UpperLimit', 1);
ActionInfo.Name = 'Actions for power allocation, subchannel selection, UAV movement, SIC order';
% Call superclass constructor
this = this@rl.env.MATLABEnvironment(ObservationInfo, ActionInfo);
Anywhere in the copied code, do you have a return statement? No.
Anywhere in the copied code, do you use the this object? Yes. There are five such references (used in a couple places) that I can see.
this.N_max
this.numSubchannels
this.radius
this.flightHeight
this.timeSteps
If those were Constant properties and referred to them as NOMAEnv.N_max, NOMAEnv.numSubchannels, etc. I believe that you would be able to use them to create your ObservationInfo and ActionInfo variables without MATLAB considering them to be uses of the object for purposes of that guideline. It looks like you never assign a value to any of those properties other than in the properties block so making them Constant may be appropriate.
You could also refer to those properties using an instance of the object later on, so you don't have to modify the rest of your code. NOMAEnv.N_max and this.N_max (assuming this isa NOMAEnv object) should both work to access that property (except in the constructor while you're in the process of instantiating the object, where you want to access it via the class name not an instance.)
更多回答(0 个)
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!