Home > Blockchain >  How to make code like repmat MATLAB on Python?
How to make code like repmat MATLAB on Python?

Time:06-03

This MATLAB code is from Main_MOHHO.m from https://www.mathworks.com/matlabcentral/fileexchange/80776-multi-objective-harris-hawks-optimization-mohho. I want to make the same code using python, but I can't make the Rabbits variabel.

clc;
clear;
close all;
%% Problem Definition
nVar=3;             % Number of Decision Variables
VarSize=[1 nVar];   % Size of Decision Variables Matrix
VarMin=0;          % Lower Bound of Variables
VarMax=1;          % Upper Bound of Variables
nPop=5;            % Population Size
%% Initialization
empty_Rabbit.Location=[];
empty_Rabbit.Cost=[];
empty_Rabbit.Sol=[];
empty_Rabbit.IsDominated=[];
empty_Rabbit.GridIndex=[];
empty_Rabbit.GridSubIndex=[];
Rabbits=repmat(empty_Rabbit,nPop,1);
for i=1:nPop
    Rabbits(i).Location = rand(VarSize).*(VarMax-VarMin) VarMin; 
    X(i,:) = rand(VarSize).*(VarMax-VarMin) VarMin;     
end

I try to make it on google colab like this.

import numpy as np
nVar = 3 # Number of Decision Variables
VarSize = np.array((1, nVar)) # Size of Decision Variables Matrix
VarMin = 0 # Lower Bound of Variables
VarMax = 1 # Upper Bound of Variables

nPop = 5 # Population Size
class empty_Rabbit:
  Location = []
  Cost = []
  IsDominated = []
  GridIndex = []
  GridSubIndex = []
  Sol = []

Rabbits = np.tile(empty_Rabbit, (nPop, 1))
X = np.zeros((nPop, nVar))
Rabbit_Location = np.zeros((VarSize))
Rabbit_Energy = math.inf

for i in range(nPop):
  Rabbits[i, 0].Location = np.multiply(np.random.rand(VarSize[0], VarSize[1]), 
                                       (VarMax-VarMin)   VarMin)
  print(Rabbits[i,0].Location)

But, the Rabbits_Location same for each row.

Output Google Colab

What is the correct way to create Rabbits variable in python so the output like the output with number 1 in the pic? Thank you.

CodePudding user response:

Two issues exist in your code. First, np.tile repeats the same object (nPop, 1) times. So, when you change one of the objects, you actually change the same memory location. Second, you want to initialize a different object each time instead of referring to the same object, so you want to write empty_Rabbit() to create a new instance of that object. Both suggestions can be achieved using a comprehension like [empty_Rabbit() for i in range(nPop)] and reshape to any new dimensions if required.

import numpy as np
nVar = 3 # Number of Decision Variables
VarSize = np.array((1, nVar)) # Size of Decision Variables Matrix
VarMin = 0 # Lower Bound of Variables
VarMax = 1 # Upper Bound of Variables

nPop = 5 # Population Size
class empty_Rabbit:
  Location = []
  Cost = []
  IsDominated = []
  GridIndex = []
  GridSubIndex = []
  Sol = []

Rabbits = np.array([empty_Rabbit() for i in range(nPop)]).reshape(nPop,1)
X = np.zeros((nPop, nVar))
Rabbit_Location = np.zeros((VarSize))
Rabbit_Energy = np.inf

for i in range(nPop):
  Rabbits[i, 0].Location = np.multiply(np.random.rand(VarSize[0], VarSize[1]), 
                                       (VarMax-VarMin)   VarMin)
  print(Rabbits[i,0].Location)

for i in range(nPop):
  print(Rabbits[i,0].Location)

Now, the output of both print statements will be identical with distinct rows:

[[0.5392264  0.39375339 0.59483626]]
[[0.53959355 0.91049574 0.58115175]]
[[0.46152304 0.43111977 0.06882631]]
[[0.13693784 0.82075653 0.49488394]]
[[0.06901317 0.34133836 0.91453956]]

[[0.5392264  0.39375339 0.59483626]]
[[0.53959355 0.91049574 0.58115175]]
[[0.46152304 0.43111977 0.06882631]]
[[0.13693784 0.82075653 0.49488394]]
[[0.06901317 0.34133836 0.91453956]]

CodePudding user response:

scipy.io.loadmat uses structured arrays when loading struct from MATLAB .mat files. But I think that's too advanced for you.

I think you need to create a set of numpy arrays, rather than try for some sort of class or more complicated structure.

empty_Rabbit.Location=[];
empty_Rabbit.Cost=[];
empty_Rabbit.Sol=[];
empty_Rabbit.IsDominated=[];
empty_Rabbit.GridIndex=[];
empty_Rabbit.GridSubIndex=[];

becomes instead

location = np.zeros(nPop)
cost = np.zeros(nPop)
sol = np.zeros(nPop)
isDominated = np.zeros(nPop)     # or bool dtype?
gridIndex = np.zeros(nPop)
gridSubIndex = np.zeros(nPop)

np.zeros makes a float array; for some of those you might want np.zeros(nPop, dtype=int) (if used as index).

 rabbit= np.zeros(nPop, dtype=[('location',float), ('cost',float),('sol',float), ....])

could be used to make structured array, but you'll need to read more about those.

MATLAB lets you use iteration freely as in

for i=1:nPop
    Rabbits(i).Location = rand(VarSize).*(VarMax-VarMin) VarMin; 
    X(i,:) = rand(VarSize).*(VarMax-VarMin) VarMin;     
end

but that's slow (as it used to be MATLAB before jit compilation). It's better to use whole array calculations

location = np.random.rand(nPop,VarSize) * (VarMax-VarMin) VarMin

will make a (nPop,VarSize) 2d array, not the 1d that np.zeros(nPop) created.

Looks like X could be created in the same way (without iteration).

  • Related