ruby - Strange code execution: should assign one element, assigns all -


i trying write genetic algorithm function approximation. part of code responsible mutation of 1 gene changes whole chromosome array. changes array not used in part. here's code.

print "\n\nchrom_array5: ", @chrom_array     print "\n\nchrom_array5: ", @chrom_array     random = rand  if @no_of_chrom*@no_of_variables*@mutation_rate > random      z=( rand * @no_of_chrom ).to_i           print "\n\nz: ", z           v=( rand * @no_of_variables).to_i           print "\n\nv: ", v           ble=new_chrom_array[0][0]           print "\nnew_chrom_array[0][0]: ", new_chrom_array           new_chrom_array[z][v] =   ble + ble*rand - ble*random           print "\nnew_chrom_array[z][v]: ", new_chrom_array   end        print "\n\nchrom_array6: ", @chrom_array       print "\nnew_chrom_array6: ", new_chrom_array        @chrom_array = new_chrom_array        ...    

here's output mutating iteration:

chrom_array5: [[128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78]]

new_chrom_array5: [[128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78]]

z: 2

v: 0

new_chrom_array[0][0]: [[128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78]]

new_chrom_array[z][v]: [[143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22]]

chrom_array6: [[143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22]]

new_chrom_array6: [[143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22]]

do know reason such behaviour?

one way can happen if elements of new_chrom_array contain same object. example, using irb interactively execute ruby code:

~ ∙ irb irb(main):001:0> sub_array = [1] => [1] irb(main):002:0> array1 = [sub_array, sub_array, sub_array] => [[1], [1], [1]] irb(main):003:0> array2 = [sub_array, sub_array, sub_array, sub_array] => [[1], [1], [1], [1]] irb(main):004:0> array1[1][0] = 'x' => "x" irb(main):005:0> array1 => [["x"], ["x"], ["x"]] irb(main):006:0> array2 => [["x"], ["x"], ["x"], ["x"]] 

so here making assignment array[1][0] affects both array1 , array2 because object in of elements sub_array.

this can confirmed looking @ object_id of array elements:

irb(main):007:0> array1[0].object_id => 70353532235320 irb(main):008:0> array1[1].object_id => 70353532235320 irb(main):009:0> array2[1].object_id => 70353532235320 

in experience there couple of things cause this:

creating array using array.new use same object of elements:

irb(main):010:0> = array.new(5, ['x']) => [["x"], ["x"], ["x"], ["x"], ["x"]] irb(main):011:0> a[0].object_id => 70353539884820 irb(main):012:0> a[4].object_id => 70353539884820 

you can avoid using block initialize elements, block return new object each time called - note different object_ids

irb(main):013:0> b = array.new(5) {['x']} => [["x"], ["x"], ["x"], ["x"], ["x"]] irb(main):014:0> b[0].object_id => 70353535993240 irb(main):015:0> b[4].object_id => 70353535992900 

the second common problem use of .dup make copies of array , not remembering makes shallow copy:

irb(main):016:0> a1 = [['x']] => [["x"]] irb(main):017:0> a2 = a1.dup => [["x"]] irb(main):018:0> a2[0][0] = 'y' => "y" irb(main):019:0> a1 => [["y"]] irb(main):020:0> a2 => [["y"]] 

you can use object_id see contents of arrays are. 1 way deep copy divorces copy original use ruby's marshal make copy of data structure - here see altering a3 doesn't affect a1

irb(main):021:0> a3 = marshal.load(marshal.dump(a1)) => [["y"]] irb(main):022:0> a3[0][0] = 'z' => "z" irb(main):023:0> a1   => [["y"]] 

Comments

Popular posts from this blog

apache - Remove .php and add trailing slash in url using htaccess not loading css -

javascript - jQuery show full size image on click -